diff --git a/include/wx/richtext/richtextborderspage.h b/include/wx/richtext/richtextborderspage.h index 17ec6884ae..26148cb820 100644 --- a/include/wx/richtext/richtextborderspage.h +++ b/include/wx/richtext/richtextborderspage.h @@ -158,6 +158,9 @@ public: /// wxEVT_UPDATE_UI event handler for ID_RICHTEXT_OUTLINE_SYNCHRONIZE void OnRichtextOutlineSynchronizeUpdate( wxUpdateUIEvent& event ); + /// wxEVT_UPDATE_UI event handler for ID_RICHTEXTBORDERSPAGE_CORNER_TEXT + void OnRichtextborderspageCornerUpdate( wxUpdateUIEvent& event ); + ////@end wxRichTextBordersPage event handler declarations ////@begin wxRichTextBordersPage member function declarations @@ -215,6 +218,9 @@ public: wxComboBox* m_bottomOutlineStyle; wxRichTextColourSwatchCtrl* m_bottomOutlineColour; wxCheckBox* m_outlineSyncCtrl; + wxCheckBox* m_cornerRadiusCheckBox; + wxTextCtrl* m_cornerRadiusText; + wxComboBox* m_cornerRadiusUnits; wxRichTextBorderPreviewCtrl* m_borderPreviewCtrl; /// Control identifiers enum { @@ -264,6 +270,10 @@ public: ID_RICHTEXT_OUTLINE_BOTTOM_STYLE = 10842, ID_RICHTEXT_OUTLINE_BOTTOM_COLOUR = 10843, ID_RICHTEXT_OUTLINE_SYNCHRONIZE = 10846, + ID_RICHTEXTBORDERSPAGE_CORNER = 10847, + ID_RICHTEXTBORDERSPAGE_CORNER_CHECKBOX = 10848, + ID_RICHTEXTBORDERSPAGE_CORNER_TEXT = 10849, + ID_RICHTEXTBORDERSPAGE_CORNER_UNITS = 10850, ID_RICHTEXT_BORDER_PREVIEW = 10844 }; ////@end wxRichTextBordersPage member variables diff --git a/include/wx/richtext/richtextbuffer.h b/include/wx/richtext/richtextbuffer.h index e4326d9bfb..45e8af0445 100644 --- a/include/wx/richtext/richtextbuffer.h +++ b/include/wx/richtext/richtextbuffer.h @@ -305,7 +305,8 @@ enum wxTextBoxAttrFlags wxTEXT_BOX_ATTR_COLLAPSE_BORDERS = 0x00000004, wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT = 0x00000008, wxTEXT_BOX_ATTR_BOX_STYLE_NAME = 0x00000010, - wxTEXT_BOX_ATTR_WHITESPACE = 0x00000020 + wxTEXT_BOX_ATTR_WHITESPACE = 0x00000020, + wxTEXT_BOX_ATTR_CORNER_RADIUS = 0x00000040 }; /** @@ -1278,6 +1279,22 @@ public: */ bool HasWhitespaceMode() const { return HasFlag(wxTEXT_BOX_ATTR_WHITESPACE); } + /** + Returns @true if the corner radius flag is present. + */ + bool HasCornerRadius() const { return HasFlag(wxTEXT_BOX_ATTR_CORNER_RADIUS); } + + /** + Returns the corner radius value. + */ + const wxTextAttrDimension& GetCornerRadius() const { return m_cornerRadius; } + wxTextAttrDimension& GetCornerRadius() { return m_cornerRadius; } + + /** + Sets the corner radius value. + */ + void SetCornerRadius(const wxTextAttrDimension& dim) { m_cornerRadius = dim; m_flags |= wxTEXT_BOX_ATTR_CORNER_RADIUS; } + /** Returns the vertical alignment. */ @@ -1525,6 +1542,7 @@ public: wxTextBoxAttrCollapseMode m_collapseMode; wxTextBoxAttrVerticalAlignment m_verticalAlignment; wxTextBoxAttrWhitespaceMode m_whitespaceMode; + wxTextAttrDimension m_cornerRadius; wxString m_boxStyleName; }; @@ -2793,7 +2811,7 @@ public: /** Draws a border. */ - static bool DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxTextAttrBorders& attr, const wxRect& rect, int flags = 0); + static bool DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxRichTextAttr& attr, const wxTextAttrBorders& borders, const wxRect& rect, int flags = 0); /** Returns the various rectangles of the box model in pixels. You can either specify @a contentRect (inner) diff --git a/interface/wx/richtext/richtextbuffer.h b/interface/wx/richtext/richtextbuffer.h index 30de6f76ba..38834746fa 100644 --- a/interface/wx/richtext/richtextbuffer.h +++ b/interface/wx/richtext/richtextbuffer.h @@ -185,7 +185,8 @@ enum wxTextBoxAttrFlags wxTEXT_BOX_ATTR_COLLAPSE_BORDERS = 0x00000004, wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT = 0x00000008, wxTEXT_BOX_ATTR_BOX_STYLE_NAME = 0x00000010, - wxTEXT_BOX_ATTR_WHITESPACE = 0x00000020 + wxTEXT_BOX_ATTR_WHITESPACE = 0x00000020, + wxTEXT_BOX_ATTR_CORNER_RADIUS = 0x00000040 }; /** @@ -1126,6 +1127,22 @@ public: */ bool HasWhitespaceMode() const { return HasFlag(wxTEXT_BOX_ATTR_WHITESPACE); } + /** + Returns @true if the corner radius flag is present. + */ + bool HasCornerRadius() const { return HasFlag(wxTEXT_BOX_ATTR_CORNER_RADIUS); } + + /** + Returns the corner radius value. + */ + const wxTextAttrDimension& GetCornerRadius() const { return m_cornerRadius; } + wxTextAttrDimension& GetCornerRadius() { return m_cornerRadius; } + + /** + Sets the corner radius value. + */ + void SetCornerRadius(const wxTextAttrDimension& dim) { m_cornerRadius = dim; m_flags |= wxTEXT_BOX_ATTR_CORNER_RADIUS; } + /** Returns the vertical alignment. */ @@ -1373,6 +1390,7 @@ public: wxTextBoxAttrCollapseMode m_collapseMode; wxTextBoxAttrVerticalAlignment m_verticalAlignment; wxTextBoxAttrWhitespaceMode m_whitespaceMode; + wxTextAttrDimension m_cornerRadius; wxString m_boxStyleName; }; @@ -2635,7 +2653,7 @@ public: /** Draws a border. */ - static bool DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxTextAttrBorders& attr, const wxRect& rect, int flags = 0); + static bool DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxRichTextAttr& attr, const wxTextAttrBorders& borders, const wxRect& rect, int flags = 0); /** Returns the various rectangles of the box model in pixels. You can either specify @a contentRect (inner) diff --git a/src/richtext/richtextborderspage.cpp b/src/richtext/richtextborderspage.cpp index 66fb1659bf..95e6c66620 100644 --- a/src/richtext/richtextborderspage.cpp +++ b/src/richtext/richtextborderspage.cpp @@ -92,6 +92,8 @@ BEGIN_EVENT_TABLE( wxRichTextBordersPage, wxRichTextDialogPage ) EVT_UPDATE_UI( ID_RICHTEXT_OUTLINE_BOTTOM_COLOUR, wxRichTextBordersPage::OnRichtextOutlineBottomUpdate ) EVT_CHECKBOX( ID_RICHTEXT_OUTLINE_SYNCHRONIZE, wxRichTextBordersPage::OnRichtextOutlineSynchronizeClick ) EVT_UPDATE_UI( ID_RICHTEXT_OUTLINE_SYNCHRONIZE, wxRichTextBordersPage::OnRichtextOutlineSynchronizeUpdate ) + EVT_UPDATE_UI( ID_RICHTEXTBORDERSPAGE_CORNER_TEXT, wxRichTextBordersPage::OnRichtextborderspageCornerUpdate ) + EVT_UPDATE_UI( ID_RICHTEXTBORDERSPAGE_CORNER_UNITS, wxRichTextBordersPage::OnRichtextborderspageCornerUpdate ) ////@end wxRichTextBordersPage event table entries END_EVENT_TABLE() @@ -194,6 +196,9 @@ void wxRichTextBordersPage::Init() m_bottomOutlineStyle = NULL; m_bottomOutlineColour = NULL; m_outlineSyncCtrl = NULL; + m_cornerRadiusCheckBox = NULL; + m_cornerRadiusText = NULL; + m_cornerRadiusUnits = NULL; m_borderPreviewCtrl = NULL; ////@end wxRichTextBordersPage member initialisation } @@ -553,6 +558,51 @@ void wxRichTextBordersPage::CreateControls() itemNotebook4->AddPage(itemPanel48, _("Outline")); + wxPanel* itemPanel91 = new wxPanel( itemNotebook4, ID_RICHTEXTBORDERSPAGE_CORNER, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxTAB_TRAVERSAL ); + wxBoxSizer* itemBoxSizer92 = new wxBoxSizer(wxVERTICAL); + itemPanel91->SetSizer(itemBoxSizer92); + + wxBoxSizer* itemBoxSizer93 = new wxBoxSizer(wxVERTICAL); + itemBoxSizer92->Add(itemBoxSizer93, 1, wxGROW|wxALL, 5); + wxBoxSizer* itemBoxSizer94 = new wxBoxSizer(wxHORIZONTAL); + itemBoxSizer93->Add(itemBoxSizer94, 0, wxGROW, 5); + wxStaticText* itemStaticText95 = new wxStaticText( itemPanel91, wxID_STATIC, _("Corner"), wxDefaultPosition, wxDefaultSize, 0 ); + itemStaticText95->SetFont(wxFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).GetPointSize(), wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).GetFamily(), wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).GetStyle(), wxBOLD, false, wxT(""))); + itemBoxSizer94->Add(itemStaticText95, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxStaticLine* itemStaticLine96 = new wxStaticLine( itemPanel91, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + itemBoxSizer94->Add(itemStaticLine96, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxFlexGridSizer* itemFlexGridSizer97 = new wxFlexGridSizer(0, 2, 0, 0); + itemBoxSizer93->Add(itemFlexGridSizer97, 0, wxALIGN_LEFT, 5); + m_cornerRadiusCheckBox = new wxCheckBox( itemPanel91, ID_RICHTEXTBORDERSPAGE_CORNER_CHECKBOX, _("Corner &radius:"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER ); + m_cornerRadiusCheckBox->SetValue(false); + m_cornerRadiusCheckBox->SetHelpText(_("An optional corner radius for adding rounded corners.")); + if (wxRichTextBordersPage::ShowToolTips()) + m_cornerRadiusCheckBox->SetToolTip(_("An optional corner radius for adding rounded corners.")); + itemFlexGridSizer97->Add(m_cornerRadiusCheckBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxBoxSizer* itemBoxSizer99 = new wxBoxSizer(wxHORIZONTAL); + itemFlexGridSizer97->Add(itemBoxSizer99, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); + m_cornerRadiusText = new wxTextCtrl( itemPanel91, ID_RICHTEXTBORDERSPAGE_CORNER_TEXT, wxEmptyString, wxDefaultPosition, wxSize(50, -1), 0 ); + m_cornerRadiusText->SetHelpText(_("The value of the corner radius.")); + if (wxRichTextBordersPage::ShowToolTips()) + m_cornerRadiusText->SetToolTip(_("The value of the corner radius.")); + itemBoxSizer99->Add(m_cornerRadiusText, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxTOP|wxBOTTOM, 5); + + wxArrayString m_cornerRadiusUnitsStrings; + m_cornerRadiusUnitsStrings.Add(_("px")); + m_cornerRadiusUnitsStrings.Add(_("cm")); + m_cornerRadiusUnitsStrings.Add(_("pt")); + m_cornerRadiusUnits = new wxComboBox( itemPanel91, ID_RICHTEXTBORDERSPAGE_CORNER_UNITS, _("px"), wxDefaultPosition, wxSize(60, -1), m_cornerRadiusUnitsStrings, wxCB_READONLY ); + m_cornerRadiusUnits->SetStringSelection(_("px")); + m_cornerRadiusUnits->SetHelpText(_("Units for the corner radius.")); + if (wxRichTextBordersPage::ShowToolTips()) + m_cornerRadiusUnits->SetToolTip(_("Units for the corner radius.")); + itemBoxSizer99->Add(m_cornerRadiusUnits, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + + itemNotebook4->AddPage(itemPanel91, _("Corner")); + itemBoxSizer3->Add(itemNotebook4, 0, wxGROW|wxALL, 5); m_borderPreviewCtrl = new wxRichTextBorderPreviewCtrl( itemRichTextDialogPage1, ID_RICHTEXT_BORDER_PREVIEW, wxDefaultPosition, wxSize(60, 60), wxBORDER_THEME ); @@ -695,6 +745,29 @@ bool wxRichTextBordersPage::TransferDataToWindow() SetBorderValue(GetAttributes()->GetTextBoxAttr().GetOutline().GetTop(), m_topOutlineWidth, m_topOutlineWidthUnits, m_topOutlineCheckbox, m_topOutlineStyle, m_topOutlineColour, m_borderStyles); SetBorderValue(GetAttributes()->GetTextBoxAttr().GetOutline().GetBottom(), m_bottomOutlineWidth, m_bottomOutlineWidthUnits, m_bottomOutlineCheckbox, m_bottomOutlineStyle, m_bottomOutlineColour, m_borderStyles); + // Corner radius + if (!GetAttributes()->GetTextBoxAttr().HasCornerRadius()) + { + m_cornerRadiusCheckBox->Set3StateValue(wxCHK_UNDETERMINED); + m_cornerRadiusText->SetValue(wxT("0")); + m_cornerRadiusUnits->SetSelection(0); + } + else + { + wxArrayInt units; + units.Add(wxTEXT_ATTR_UNITS_PIXELS); + units.Add(wxTEXT_ATTR_UNITS_TENTHS_MM); + units.Add(wxTEXT_ATTR_UNITS_HUNDREDTHS_POINT); + + wxRichTextFormattingDialog::SetDimensionValue(GetAttributes()->GetTextBoxAttr().GetCornerRadius(), m_cornerRadiusText, m_cornerRadiusUnits, NULL, + & units); + + if (GetAttributes()->GetTextBoxAttr().GetCornerRadius().GetValue() == 0) + m_cornerRadiusCheckBox->Set3StateValue(wxCHK_UNCHECKED); + else + m_cornerRadiusCheckBox->Set3StateValue(wxCHK_CHECKED); + } + m_ignoreUpdates = false; UpdateSyncControls(); @@ -716,6 +789,33 @@ bool wxRichTextBordersPage::TransferDataFromWindow() GetBorderValue(GetAttributes()->GetTextBoxAttr().GetOutline().GetTop(), m_topOutlineWidth, m_topOutlineWidthUnits, m_topOutlineCheckbox, m_topOutlineStyle, m_topOutlineColour, m_borderStyles); GetBorderValue(GetAttributes()->GetTextBoxAttr().GetOutline().GetBottom(), m_bottomOutlineWidth, m_bottomOutlineWidthUnits, m_bottomOutlineCheckbox, m_bottomOutlineStyle, m_bottomOutlineColour, m_borderStyles); + // Corner radius + { + wxArrayInt units; + units.Add(wxTEXT_ATTR_UNITS_PIXELS); + units.Add(wxTEXT_ATTR_UNITS_TENTHS_MM); + units.Add(wxTEXT_ATTR_UNITS_HUNDREDTHS_POINT); + + wxRichTextFormattingDialog::GetDimensionValue(GetAttributes()->GetTextBoxAttr().GetCornerRadius(), m_cornerRadiusText, m_cornerRadiusUnits, NULL, + & units); + + if (m_cornerRadiusCheckBox->Get3StateValue() == wxCHK_UNDETERMINED) + { + // When we apply the attributes, we won't apply this one, to leave the original unchanged. + GetAttributes()->GetTextBoxAttr().GetCornerRadius().Reset(); + GetAttributes()->GetTextBoxAttr().RemoveFlag(wxTEXT_BOX_ATTR_CORNER_RADIUS); + } + else if (m_cornerRadiusCheckBox->Get3StateValue() == wxCHK_UNCHECKED) + { + GetAttributes()->GetTextBoxAttr().GetCornerRadius().SetValue(0); + GetAttributes()->GetTextBoxAttr().AddFlag(wxTEXT_BOX_ATTR_CORNER_RADIUS); + } + else + { + GetAttributes()->GetTextBoxAttr().AddFlag(wxTEXT_BOX_ATTR_CORNER_RADIUS); + } + } + return true; } @@ -884,6 +984,16 @@ void wxRichTextBordersPage::OnRichtextOutlineBottomUpdate( wxUpdateUIEvent& even event.Enable(m_bottomOutlineCheckbox->Get3StateValue() == wxCHK_CHECKED && !m_outlineSyncCtrl->GetValue()); } + +/*! + * wxEVT_UPDATE_UI event handler for ID_RICHTEXTBORDERSPAGE_CORNER_TEXT + */ + +void wxRichTextBordersPage::OnRichtextborderspageCornerUpdate( wxUpdateUIEvent& event ) +{ + event.Enable(m_cornerRadiusCheckBox->Get3StateValue() == wxCHK_CHECKED); +} + /*! * wxEVT_CHECKBOX event handler for ID_RICHTEXT_BORDER_LEFT_CHECKBOX */ @@ -1238,19 +1348,26 @@ void wxRichTextBorderPreviewCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxRect rect = GetClientRect(); + wxRichTextAttr attr; + attr.GetTextBoxAttr().GetBorder() = m_attributes->GetTextBoxAttr().GetBorder(); + attr.GetTextBoxAttr().GetOutline() = m_attributes->GetTextBoxAttr().GetOutline(); + if (m_attributes->GetTextBoxAttr().HasCornerRadius()) + attr.GetTextBoxAttr().SetCornerRadius(m_attributes->GetTextBoxAttr().GetCornerRadius()); + if (m_attributes->HasBackgroundColour()) + attr.SetBackgroundColour(m_attributes->GetBackgroundColour()); + + wxTextAttrDimension marginDim(10, wxTEXT_ATTR_UNITS_PIXELS); + attr.GetTextBoxAttr().GetMargins().GetLeft() = marginDim; + attr.GetTextBoxAttr().GetMargins().GetTop() = marginDim; + attr.GetTextBoxAttr().GetMargins().GetRight() = marginDim; + attr.GetTextBoxAttr().GetMargins().GetBottom() = marginDim; + int margin = 10; rect.x += margin; rect.y += margin; rect.width -= 2*margin; rect.height -= 2*margin; - wxRichTextObject::DrawBorder(dc, NULL, m_attributes->GetTextBoxAttr().GetOutline(), rect); - - rect.x += margin; - rect.y += margin; - rect.width -= 2*margin; - rect.height -= 2*margin; - - wxRichTextObject::DrawBorder(dc, NULL, m_attributes->GetTextBoxAttr().GetBorder(), rect); + wxRichTextObject::DrawBoxAttributes(dc, NULL, attr, rect); } } diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index 52ff7c52ba..eee9efcf37 100644 --- a/src/richtext/richtextbuffer.cpp +++ b/src/richtext/richtextbuffer.cpp @@ -685,11 +685,23 @@ bool wxRichTextObject::DrawBoxAttributes(wxDC& dc, wxRichTextBuffer* buffer, con colour = attr.GetBackgroundColour(); wxPen pen(colour); + pen.SetJoin(wxJOIN_MITER); wxBrush brush(colour); dc.SetPen(pen); dc.SetBrush(brush); - dc.DrawRectangle(borderRect); + + if (attr.GetTextBoxAttr().HasCornerRadius() && attr.GetTextBoxAttr().GetCornerRadius().GetValue() > 0) + { + wxTextAttrDimensionConverter converter(dc, buffer ? buffer->GetScale() : 1.0); + int cornerRadius = converter.GetPixels(attr.GetTextBoxAttr().GetCornerRadius()); + if (cornerRadius > 0) + { + dc.DrawRoundedRectangle(borderRect, cornerRadius); + } + } + else + dc.DrawRectangle(borderRect); } if (flags & wxRICHTEXT_DRAW_GUIDELINES) @@ -712,46 +724,85 @@ bool wxRichTextObject::DrawBoxAttributes(wxDC& dc, wxRichTextBuffer* buffer, con } } - DrawBorder(dc, buffer, editBorderAttr.GetTextBoxAttr().GetBorder(), borderRect, flags); + DrawBorder(dc, buffer, attr, editBorderAttr.GetTextBoxAttr().GetBorder(), borderRect, flags); } if (attr.GetTextBoxAttr().GetBorder().IsValid()) - DrawBorder(dc, buffer, attr.GetTextBoxAttr().GetBorder(), borderRect); + DrawBorder(dc, buffer, attr, attr.GetTextBoxAttr().GetBorder(), borderRect); if (attr.GetTextBoxAttr().GetOutline().IsValid()) - DrawBorder(dc, buffer, attr.GetTextBoxAttr().GetOutline(), outlineRect); + DrawBorder(dc, buffer, attr, attr.GetTextBoxAttr().GetOutline(), outlineRect); return true; } // Draw a border -bool wxRichTextObject::DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxTextAttrBorders& attr, const wxRect& rect, int WXUNUSED(flags)) +bool wxRichTextObject::DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxRichTextAttr& attr, const wxTextAttrBorders& borders, const wxRect& rect, int WXUNUSED(flags)) { int borderLeft = 0, borderRight = 0, borderTop = 0, borderBottom = 0; wxTextAttrDimensionConverter converter(dc, buffer ? buffer->GetScale() : 1.0); - if (attr.GetLeft().IsValid() && attr.GetLeft().GetStyle() != wxTEXT_BOX_ATTR_BORDER_NONE) + // If we have a corner radius, assume all borders are the same, and draw a rounded outline. + if (attr.GetTextBoxAttr().HasCornerRadius() && borders.GetLeft().IsValid() && borders.GetLeft().GetStyle() != wxTEXT_BOX_ATTR_BORDER_NONE) { - borderLeft = converter.GetPixels(attr.GetLeft().GetWidth()); - wxColour col(attr.GetLeft().GetColour()); - - // If pen width is > 1, resorts to a solid rectangle. - if (borderLeft == 1) + int cornerRadius = converter.GetPixels(attr.GetTextBoxAttr().GetCornerRadius()); + if (cornerRadius > 0) { + borderLeft = converter.GetPixels(borders.GetLeft().GetWidth()); + wxColour col(borders.GetLeft().GetColour()); int penStyle = wxSOLID; - if (attr.GetLeft().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DOTTED) + if (borders.GetLeft().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DOTTED) penStyle = wxDOT; - else if (attr.GetLeft().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DASHED) + else if (borders.GetLeft().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DASHED) penStyle = wxLONG_DASH; - wxPen pen(col, 1, penStyle); + wxPen pen(col, borderLeft, penStyle); dc.SetPen(pen); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRoundedRectangle(rect, cornerRadius); + return true; + } + } + // Draw the border in one go if all the borders are the same + if (borders.GetLeft().IsValid() && borders.GetTop().IsValid() && borders.GetRight().IsValid() &&borders.GetBottom().IsValid() && + (borders.GetLeft() == borders.GetTop()) && (borders.GetLeft() == borders.GetRight()) && (borders.GetLeft() == borders.GetBottom())) + { + borderLeft = converter.GetPixels(borders.GetLeft().GetWidth()); + wxColour col(borders.GetLeft().GetColour()); + int penStyle = wxSOLID; + if (borders.GetLeft().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DOTTED) + penStyle = wxDOT; + else if (borders.GetLeft().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DASHED) + penStyle = wxLONG_DASH; + wxPen pen(col, borderLeft, penStyle); + pen.SetJoin(wxJOIN_MITER); + dc.SetPen(pen); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRectangle(rect); + return true; + } + + if (borders.GetLeft().IsValid() && (borders.GetLeft().GetWidth().GetValue() > 0) && (borders.GetLeft().GetStyle() != wxTEXT_BOX_ATTR_BORDER_NONE)) + { + borderLeft = converter.GetPixels(borders.GetLeft().GetWidth()); + wxColour col(borders.GetLeft().GetColour()); + int penStyle = wxSOLID; + if (borders.GetLeft().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DOTTED) + penStyle = wxDOT; + else if (borders.GetLeft().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DASHED) + penStyle = wxLONG_DASH; + + if (borderLeft == 1 || penStyle != wxSOLID) + { + wxPen pen(col, borderLeft, penStyle); + dc.SetPen(pen); // Note that the last point is not drawn. dc.DrawLine(rect.x, rect.y, rect.x, rect.y + rect.height); } - else if (borderLeft > 1) + else { wxPen pen(col); + pen.SetJoin(wxJOIN_MITER); wxBrush brush(col); dc.SetPen(pen); dc.SetBrush(brush); @@ -759,28 +810,28 @@ bool wxRichTextObject::DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxTe } } - if (attr.GetRight().IsValid() && attr.GetRight().GetStyle() != wxTEXT_BOX_ATTR_BORDER_NONE) + if (borders.GetRight().IsValid() && (borders.GetRight().GetWidth().GetValue() > 0) && (borders.GetRight().GetStyle() != wxTEXT_BOX_ATTR_BORDER_NONE)) { - borderRight = converter.GetPixels(attr.GetRight().GetWidth()); + borderRight = converter.GetPixels(borders.GetRight().GetWidth()); - wxColour col(attr.GetRight().GetColour()); + wxColour col(borders.GetRight().GetColour()); + int penStyle = wxSOLID; + if (borders.GetRight().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DOTTED) + penStyle = wxDOT; + else if (borders.GetRight().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DASHED) + penStyle = wxLONG_DASH; - // If pen width is > 1, resorts to a solid rectangle. - if (borderRight == 1) + if (borderRight == 1 || penStyle != wxSOLID) { - int penStyle = wxSOLID; - if (attr.GetRight().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DOTTED) - penStyle = wxDOT; - else if (attr.GetRight().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DASHED) - penStyle = wxLONG_DASH; - wxPen pen(col, 1, penStyle); + wxPen pen(col, borderRight, penStyle); dc.SetPen(pen); // Note that the last point is not drawn. dc.DrawLine(rect.x + rect.width - 1, rect.y, rect.x + rect.width - 1, rect.y + rect.height); } - else if (borderRight > 1) + else { wxPen pen(col); + pen.SetJoin(wxJOIN_MITER); wxBrush brush(col); dc.SetPen(pen); dc.SetBrush(brush); @@ -788,28 +839,32 @@ bool wxRichTextObject::DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxTe } } - if (attr.GetTop().IsValid() && attr.GetTop().GetStyle() != wxTEXT_BOX_ATTR_BORDER_NONE) + if (borders.GetTop().IsValid() && (borders.GetTop().GetWidth().GetValue() > 0) && (borders.GetTop().GetStyle() != wxTEXT_BOX_ATTR_BORDER_NONE)) { - borderTop = converter.GetPixels(attr.GetTop().GetWidth()); + borderTop = converter.GetPixels(borders.GetTop().GetWidth()); - wxColour col(attr.GetTop().GetColour()); + wxColour col(borders.GetTop().GetColour()); + int penStyle = wxSOLID; + if (borders.GetRight().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DOTTED) + penStyle = wxDOT; + else if (borders.GetRight().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DASHED) + penStyle = wxLONG_DASH; - // If pen width is > 1, resorts to a solid rectangle. - if (borderTop == 1) + if (borderTop == 1 || penStyle != wxSOLID) { int penStyle = wxSOLID; - if (attr.GetTop().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DOTTED) + if (borders.GetTop().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DOTTED) penStyle = wxDOT; - else if (attr.GetTop().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DASHED) + else if (borders.GetTop().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DASHED) penStyle = wxLONG_DASH; - wxPen pen(col, 1, penStyle); + wxPen pen(col, borderTop, penStyle); dc.SetPen(pen); dc.DrawLine(rect.x, rect.y, rect.x + rect.width, rect.y); - } - else if (borderTop > 1) + else { wxPen pen(col); + pen.SetJoin(wxJOIN_MITER); wxBrush brush(col); dc.SetPen(pen); dc.SetBrush(brush); @@ -817,26 +872,26 @@ bool wxRichTextObject::DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxTe } } - if (attr.GetBottom().IsValid() && attr.GetBottom().GetStyle() != wxTEXT_BOX_ATTR_BORDER_NONE) + if (borders.GetBottom().IsValid() && (borders.GetBottom().GetWidth().GetValue() > 0) && (borders.GetBottom().GetStyle() != wxTEXT_BOX_ATTR_BORDER_NONE)) { - borderBottom = converter.GetPixels(attr.GetBottom().GetWidth()); - wxColour col(attr.GetBottom().GetColour()); + borderBottom = converter.GetPixels(borders.GetBottom().GetWidth()); + wxColour col(borders.GetBottom().GetColour()); + int penStyle = wxSOLID; + if (borders.GetBottom().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DOTTED) + penStyle = wxDOT; + else if (borders.GetBottom().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DASHED) + penStyle = wxLONG_DASH; - // If pen width is > 1, resorts to a solid rectangle. - if (borderBottom == 1) + if (borderBottom == 1 || penStyle != wxSOLID) { - int penStyle = wxSOLID; - if (attr.GetBottom().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DOTTED) - penStyle = wxDOT; - else if (attr.GetBottom().GetStyle() == wxTEXT_BOX_ATTR_BORDER_DASHED) - penStyle = wxLONG_DASH; - wxPen pen(col, 1, penStyle); + wxPen pen(col, borderBottom, penStyle); dc.SetPen(pen); dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height - 1); } - else if (borderBottom > 1) + else { wxPen pen(col); + pen.SetJoin(wxJOIN_MITER); wxBrush brush(col); dc.SetPen(pen); dc.SetBrush(brush); @@ -9663,7 +9718,7 @@ bool wxRichTextTable::Draw(wxDC& dc, wxRichTextDrawingContext& context, const wx wxRect contentRect, borderRect, paddingRect, outlineRect; cell->GetBoxRects(dc, GetBuffer(), attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); - cell->DrawBorder(dc, GetBuffer(), attr.GetTextBoxAttr().GetBorder(), borderRect); + cell->DrawBorder(dc, GetBuffer(), attr, attr.GetTextBoxAttr().GetBorder(), borderRect); } } } @@ -12972,6 +13027,7 @@ void wxTextBoxAttr::Reset() m_border.Reset(); m_outline.Reset(); + m_cornerRadius.Reset(); } // Equality test @@ -12984,6 +13040,7 @@ bool wxTextBoxAttr::operator== (const wxTextBoxAttr& attr) const m_whitespaceMode == attr.m_whitespaceMode && m_collapseMode == attr.m_collapseMode && m_verticalAlignment == attr.m_verticalAlignment && + m_cornerRadius == attr.m_cornerRadius && m_margins == attr.m_margins && m_padding == attr.m_padding && @@ -13009,6 +13066,7 @@ bool wxTextBoxAttr::EqPartial(const wxTextBoxAttr& attr, bool weakTest) const (!HasCollapseBorders() && attr.HasCollapseBorders()) || (!HasVerticalAlignment() && attr.HasVerticalAlignment()) || (!HasWhitespaceMode() && attr.HasWhitespaceMode()) || + (!HasCornerRadius() && attr.HasCornerRadius()) || (!HasBoxStyleName() && attr.HasBoxStyleName()))) { return false; @@ -13028,6 +13086,9 @@ bool wxTextBoxAttr::EqPartial(const wxTextBoxAttr& attr, bool weakTest) const if (attr.HasWhitespaceMode() && HasWhitespaceMode() && (GetWhitespaceMode() != attr.GetWhitespaceMode())) return false; + if (attr.HasCornerRadius() && HasCornerRadius() && !(attr.GetCornerRadius() == GetCornerRadius())) + return false; + if (attr.HasBoxStyleName() && HasBoxStyleName() && (attr.GetBoxStyleName() != GetBoxStyleName())) return false; @@ -13103,6 +13164,11 @@ bool wxTextBoxAttr::Apply(const wxTextBoxAttr& attr, const wxTextBoxAttr* compar SetWhitespaceMode(attr.GetWhitespaceMode()); } + if (attr.HasCornerRadius()) + { + if (!(compareWith && compareWith->HasCornerRadius() && compareWith->GetCornerRadius() == attr.GetCornerRadius())) + SetCornerRadius(attr.GetCornerRadius()); + } if (attr.HasBoxStyleName()) { if (!(compareWith && compareWith->HasBoxStyleName() && compareWith->GetBoxStyleName() == attr.GetBoxStyleName())) @@ -13141,6 +13207,9 @@ bool wxTextBoxAttr::RemoveStyle(const wxTextBoxAttr& attr) if (attr.HasWhitespaceMode()) RemoveFlag(wxTEXT_BOX_ATTR_WHITESPACE); + if (attr.HasCornerRadius()) + RemoveFlag(wxTEXT_BOX_ATTR_CORNER_RADIUS); + if (attr.HasBoxStyleName()) { SetBoxStyleName(wxEmptyString); @@ -13260,6 +13329,26 @@ void wxTextBoxAttr::CollectCommonAttributes(const wxTextBoxAttr& attr, wxTextBox else absentAttr.AddFlag(wxTEXT_BOX_ATTR_WHITESPACE); + if (attr.HasCornerRadius()) + { + if (!clashingAttr.HasCornerRadius() && !absentAttr.HasCornerRadius()) + { + if (HasCornerRadius()) + { + if (!(GetCornerRadius() == attr.GetCornerRadius())) + { + clashingAttr.AddFlag(wxTEXT_BOX_ATTR_CORNER_RADIUS); + GetCornerRadius().Reset(); + RemoveFlag(wxTEXT_BOX_ATTR_CORNER_RADIUS); + } + } + else + SetCornerRadius(attr.GetCornerRadius()); + } + } + else + absentAttr.AddFlag(wxTEXT_BOX_ATTR_CORNER_RADIUS); + if (attr.HasBoxStyleName()) { if (!clashingAttr.HasBoxStyleName() && !absentAttr.HasBoxStyleName()) diff --git a/src/richtext/richtextdialogs.pjd b/src/richtext/richtextdialogs.pjd index 1645a9f0b1..16c4249ef6 100644 --- a/src/richtext/richtextdialogs.pjd +++ b/src/richtext/richtextdialogs.pjd @@ -20014,6 +20014,14 @@ "wbBoxSizerProxy" "Vertical" "" + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 0 0 0 @@ -27114,6 +27122,559 @@ + + "wxPanel: ID_RICHTEXTBORDERSPAGE_CORNER" + "dialog-control-document" + "" + "panel" + 0 + 1 + 0 + 0 + "wbPanelProxy" + "ID_RICHTEXTBORDERSPAGE_CORNER" + 10847 + "" + "wxPanel" + "wxPanel" + 1 + 0 + "" + "" + "" + "Corner" + "" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "Tiled" + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + "" + 1 + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + "" + "" + "" + 0 + + "wxBoxSizer V" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbBoxSizerProxy" + "Vertical" + "" + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + "<Any platform>" + + "wxBoxSizer V" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbBoxSizerProxy" + "Vertical" + "" + "Expand" + "Centre" + 1 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + "<Any platform>" + + "wxBoxSizer H" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbBoxSizerProxy" + "Horizontal" + "" + "Expand" + "Centre" + 0 + 5 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "<Any platform>" + + "wxStaticText: wxID_STATIC" + "dialog-control-document" + "" + "statictext" + 0 + 1 + 0 + 0 + "wbStaticTextProxy" + "wxID_STATIC" + 5105 + "" + "wxStaticText" + "wxStaticText" + 1 + 0 + "" + "" + "" + "Corner" + -1 + "" + "" + "" + "" + "wxSYS_DEFAULT_GUI_FONT:default,default,default, wxBOLD, false" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + "" + "" + + + "wxStaticLine: wxID_STATIC" + "dialog-control-document" + "" + "staticline" + 0 + 1 + 0 + 0 + "wbStaticLineProxy" + "wxID_STATIC" + 5105 + "" + "wxStaticLine" + "wxStaticLine" + 1 + 0 + "" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 1 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + + + + "wxFlexGridSizer" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbFlexGridSizerProxy" + "" + "" + 2 + 0 + 0 + 0 + "" + "<Any platform>" + "Left" + "Centre" + 0 + 5 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + "wxCheckBox: ID_RICHTEXTBORDERSPAGE_CORNER_CHECKBOX" + "dialog-control-document" + "" + "checkbox" + 0 + 1 + 0 + 0 + "wbCheckBoxProxy" + "ID_RICHTEXTBORDERSPAGE_CORNER_CHECKBOX" + 10848 + "" + "wxCheckBox" + "wxCheckBox" + 1 + 0 + "" + "" + "m_cornerRadiusCheckBox" + "Corner &radius:" + 0 + "An optional corner radius for adding rounded corners." + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + 0 + 0 + 1 + 1 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + "" + "" + + + "wxBoxSizer H" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbBoxSizerProxy" + "Horizontal" + "" + "Left" + "Centre" + 0 + 5 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "<Any platform>" + + "wxTextCtrl: ID_RICHTEXTBORDERSPAGE_CORNER_TEXT" + "dialog-control-document" + "" + "textctrl" + 0 + 1 + 0 + 0 + "wbTextCtrlProxy" + "wxEVT_UPDATE_UI|OnRichtextborderspageCornerUpdate|NONE||wxRichTextBordersPage" + "ID_RICHTEXTBORDERSPAGE_CORNER_TEXT" + 10849 + "" + "wxTextCtrl" + "wxTextCtrl" + 1 + 0 + "" + "" + "m_cornerRadiusText" + "" + 0 + "The value of the corner radius." + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + 50 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + "" + "" + + + "wxComboBox: ID_RICHTEXTBORDERSPAGE_CORNER_UNITS" + "dialog-control-document" + "" + "combobox" + 0 + 1 + 0 + 0 + "wbComboBoxProxy" + "wxEVT_UPDATE_UI|OnRichtextborderspageCornerUpdate|NONE||wxRichTextBordersPage" + "ID_RICHTEXTBORDERSPAGE_CORNER_UNITS" + 10850 + "" + "wxComboBox" + "wxComboBox" + 1 + 0 + "" + "" + "m_cornerRadiusUnits" + "px|cm|pt" + "px" + "Units for the corner radius." + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + 60 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + "" + "" + + + + + + "wxRichTextBorderPreviewCtrl: ID_RICHTEXT_BORDER_PREVIEW" diff --git a/src/richtext/richtextxml.cpp b/src/richtext/richtextxml.cpp index b853b6fe51..65898c558b 100644 --- a/src/richtext/richtextxml.cpp +++ b/src/richtext/richtextxml.cpp @@ -1600,6 +1600,10 @@ bool wxRichTextXMLHelper::ImportStyle(wxRichTextAttr& attr, wxXmlNode* node, boo { attr.GetTextBoxAttr().GetMaxSize().GetHeight().SetValue(ParseDimension(value)); } + else if (name == wxT("corner-radius")) + { + attr.GetTextBoxAttr().SetCornerRadius(ParseDimension(value)); + } else if (name == wxT("verticalalignment")) { @@ -2186,6 +2190,7 @@ wxString wxRichTextXMLHelper::AddAttributes(const wxRichTextAttr& attr, bool isP AddAttribute(str, wxT("minheight"), attr.GetTextBoxAttr().GetMinSize().GetHeight()); AddAttribute(str, wxT("maxwidth"), attr.GetTextBoxAttr().GetMaxSize().GetWidth()); AddAttribute(str, wxT("maxheight"), attr.GetTextBoxAttr().GetMaxSize().GetHeight()); + AddAttribute(str, wxT("corner-radius"), attr.GetTextBoxAttr().GetCornerRadius()); if (attr.GetTextBoxAttr().HasVerticalAlignment()) { @@ -2665,6 +2670,7 @@ bool wxRichTextXMLHelper::AddAttributes(wxXmlNode* node, wxRichTextAttr& attr, b AddAttribute(node, wxT("minheight"), attr.GetTextBoxAttr().GetMinSize().GetHeight()); AddAttribute(node, wxT("maxwidth"), attr.GetTextBoxAttr().GetMaxSize().GetWidth()); AddAttribute(node, wxT("maxheight"), attr.GetTextBoxAttr().GetMaxSize().GetHeight()); + AddAttribute(node, wxT("corner-radius"), attr.GetTextBoxAttr().GetCornerRadius()); if (attr.GetTextBoxAttr().HasVerticalAlignment()) {