From: Vadim Zeitlin Date: Sun, 10 Sep 2006 23:57:26 +0000 (+0000) Subject: added hyperlink alignment flags (patch 1537043) X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/914f51576275c0f5411db2eed52099c71a7489a3 added hyperlink alignment flags (patch 1537043) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41153 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/docs/latex/wx/hyperlink.tex b/docs/latex/wx/hyperlink.tex index 4c0c8df4a5..0b252abfa0 100644 --- a/docs/latex/wx/hyperlink.tex +++ b/docs/latex/wx/hyperlink.tex @@ -39,8 +39,11 @@ Note that standard \helpref{wxWindow}{wxwindow} functions like \helpref{SetBackg \twocolwidtha{7cm} \begin{twocollist}\itemsep=0pt +\twocolitem{\windowstyle{wxHL\_ALIGN\_LEFT}}{Align the text to the left.} +\twocolitem{\windowstyle{wxHL\_ALIGN\_RIGHT}}{Align the text to the right.} +\twocolitem{\windowstyle{wxHL\_ALIGN\_CENTRE}}{Center the text (horizontally).} \twocolitem{\windowstyle{wxHL\_CONTEXTMENU}}{Pop up a context menu when the hyperlink is right-clicked. The context menu contains a \texttt{``Copy URL"} menu item which is automatically handled by the hyperlink and which just copies in the clipboard the URL (not the label) of the control.} -\twocolitem{\windowstyle{wxHL\_DEFAULT\_STYLE}}{The default style for wxHyperlinkCtrl: \texttt{wxNO\_BORDER|wxHL\_CONTEXTMENU}.} +\twocolitem{\windowstyle{wxHL\_DEFAULT\_STYLE}}{The default style for wxHyperlinkCtrl: \texttt{wxNO\_BORDER|wxHL\_CONTEXTMENU|wxHL\_ALIGN\_CENTRE}.} \end{twocollist} See also \helpref{window styles overview}{windowstyles}. diff --git a/include/wx/hyperlink.h b/include/wx/hyperlink.h index cfbed46e96..c7e4ac4546 100644 --- a/include/wx/hyperlink.h +++ b/include/wx/hyperlink.h @@ -23,7 +23,10 @@ // ---------------------------------------------------------------------------- #define wxHL_CONTEXTMENU 0x0001 -#define wxHL_DEFAULT_STYLE wxHL_CONTEXTMENU|wxNO_BORDER +#define wxHL_ALIGN_LEFT 0x0002 +#define wxHL_ALIGN_RIGHT 0x0004 +#define wxHL_ALIGN_CENTRE 0x0008 +#define wxHL_DEFAULT_STYLE (wxHL_CONTEXTMENU|wxNO_BORDER|wxHL_ALIGN_CENTRE) extern WXDLLIMPEXP_DATA_ADV(const wxChar) wxHyperlinkCtrlNameStr[]; @@ -96,6 +99,12 @@ protected: // Renders the hyperlink. void OnPaint(wxPaintEvent& event); + // Returns the wxRect of the label of this hyperlink. + // This is different from the clientsize's rectangle when + // clientsize != bestsize and this rectangle is influenced + // by the alignment of the label (wxHL_ALIGN_*). + wxRect GetLabelRect() const; + // If the click originates inside the bounding box of the label, // a flag is set so that an event will be fired when the left // button is released. @@ -108,7 +117,7 @@ protected: // Changes the cursor to a hand, if the mouse is inside the label's // bounding box. - void OnEnterWindow(wxMouseEvent& event); + void OnMotion(wxMouseEvent& event); // Changes the cursor back to the default, if necessary. void OnLeaveWindow(wxMouseEvent& event); @@ -116,6 +125,9 @@ protected: // handles "Copy URL" menuitem void OnPopUpCopy(wxCommandEvent& event); + // Refreshes the control to update label's position if necessary + void OnSize(wxSizeEvent& event); + // overridden base class virtuals diff --git a/samples/widgets/hyperlnk.cpp b/samples/widgets/hyperlnk.cpp index 3c2295b539..f1331d10c9 100644 --- a/samples/widgets/hyperlnk.cpp +++ b/samples/widgets/hyperlnk.cpp @@ -61,6 +61,15 @@ enum HyperlinkPage_Ctrl }; +// alignment radiobox indices +enum +{ + Align_Left, + Align_Centre, + Align_Right, + Align_Max +}; + // ---------------------------------------------------------------------------- // CheckBoxWidgetsPage // ---------------------------------------------------------------------------- @@ -83,19 +92,21 @@ protected: void OnButtonSetURL(wxCommandEvent& event); void OnButtonReset(wxCommandEvent& event); + void OnAlignment(wxCommandEvent& event); // reset the control parameters void Reset(); // (re)create the hyperctrl void CreateHyperlink(); + void CreateHyperlinkLong(long); // the controls // ------------ // the checkbox itself and the sizer it is in wxHyperlinkCtrl *m_hyperlink; - wxSizer *m_sizerHyperlink; + wxHyperlinkCtrl *m_hyperlinkLong; wxTextCtrl *m_label; wxTextCtrl *m_url; @@ -106,6 +117,8 @@ protected: // the text entries for command parameters wxTextCtrl *m_textLabel; + wxRadioBox *m_radioAlignMode; + private: DECLARE_EVENT_TABLE() DECLARE_WIDGETS_PAGE(HyperlinkWidgetsPage) @@ -119,6 +132,8 @@ BEGIN_EVENT_TABLE(HyperlinkWidgetsPage, WidgetsPage) EVT_BUTTON(HyperlinkPage_Reset, HyperlinkWidgetsPage::OnButtonReset) EVT_BUTTON(HyperlinkPage_SetLabel, HyperlinkWidgetsPage::OnButtonSetLabel) EVT_BUTTON(HyperlinkPage_SetURL, HyperlinkWidgetsPage::OnButtonSetURL) + + EVT_RADIOBOX(wxID_ANY, HyperlinkWidgetsPage::OnAlignment) END_EVENT_TABLE() // ============================================================================ @@ -150,8 +165,27 @@ void HyperlinkWidgetsPage::CreateContent() sizerLeft->Add( CreateSizerWithTextAndButton( HyperlinkPage_SetURL , wxT("Set &URL"), wxID_ANY, &m_url ), 0, wxALL | wxALIGN_RIGHT , 5 ); + static const wxString alignments[] = + { + _T("&left"), + _T("¢re"), + _T("&right") + }; + wxCOMPILE_TIME_ASSERT( WXSIZEOF(alignments) == Align_Max, + AlignMismatch ); + + m_radioAlignMode = new wxRadioBox(this, wxID_ANY, _T("alignment"), + wxDefaultPosition, wxDefaultSize, + WXSIZEOF(alignments), alignments); + m_radioAlignMode->SetSelection(1); // start with "centre" selected since + // wxHL_DEFAULT_STYLE contains wxHL_ALIGN_CENTRE + sizerLeft->Add(m_radioAlignMode, 0, wxALL|wxGROW, 5); + + + // right pane - wxSizer *sizerRight = new wxBoxSizer(wxHORIZONTAL); + wxSizer *szHyperlinkLong = new wxBoxSizer(wxVERTICAL); + wxSizer *szHyperlink = new wxBoxSizer(wxHORIZONTAL); m_visit = new wxStaticText(this, wxID_ANY, wxT("Visit ")); @@ -162,17 +196,28 @@ void HyperlinkWidgetsPage::CreateContent() m_fun = new wxStaticText(this, wxID_ANY, wxT(" for fun!")); - sizerRight->Add(0, 0, 1, wxCENTRE); - sizerRight->Add(m_visit, 0, wxCENTRE); - sizerRight->Add(m_hyperlink, 0, wxCENTRE); - sizerRight->Add(m_fun, 0, wxCENTRE); - sizerRight->Add(0, 0, 1, wxCENTRE); - sizerRight->SetMinSize(150, 0); - m_sizerHyperlink = sizerRight; // save it to modify it later + szHyperlink->Add(0, 0, 1, wxCENTRE); + szHyperlink->Add(m_visit, 0, wxCENTRE); + szHyperlink->Add(m_hyperlink, 0, wxCENTRE); + szHyperlink->Add(m_fun, 0, wxCENTRE); + szHyperlink->Add(0, 0, 1, wxCENTRE); + szHyperlink->SetMinSize(150, 0); + + m_hyperlinkLong = new wxHyperlinkCtrl(this, + wxID_ANY, + wxT("This is a long hyperlink"), + wxT("www.wxwidgets.org")); + + szHyperlinkLong->Add(0, 0, 1, wxCENTRE); + szHyperlinkLong->Add(szHyperlink, 0, wxCENTRE|wxGROW); + szHyperlinkLong->Add(0, 0, 1, wxCENTRE); + szHyperlinkLong->Add(m_hyperlinkLong, 0, wxGROW); + szHyperlinkLong->Add(0, 0, 1, wxCENTRE); + // the 3 panes panes compose the window sizerTop->Add(sizerLeft, 0, (wxALL & ~wxLEFT), 10); - sizerTop->Add(sizerRight, 1, wxGROW | (wxALL & ~wxRIGHT), 10); + sizerTop->Add(szHyperlinkLong, 1, wxGROW | (wxALL & ~wxRIGHT), 10); // final initializations Reset(); @@ -193,25 +238,42 @@ void HyperlinkWidgetsPage::CreateHyperlink() const wxString label = m_hyperlink->GetLabel(); const wxString url = m_hyperlink->GetURL(); - size_t count = m_sizerHyperlink->GetChildren().GetCount(); - for ( size_t n = 0; n < count; n++ ) - { - m_sizerHyperlink->Remove(0); - } + wxHyperlinkCtrl *hyp = new wxHyperlinkCtrl(this, + HyperlinkPage_Ctrl, + label, + url); + // update sizer's child window + GetSizer()->Replace(m_hyperlink, hyp, true); + + // update our pointer delete m_hyperlink; + m_hyperlink = hyp; - m_hyperlink = new wxHyperlinkCtrl(this, - HyperlinkPage_Ctrl, - label, - url); - - m_sizerHyperlink->Add(0, 0, 1, wxCENTRE); - m_sizerHyperlink->Add(m_visit, 0, wxCENTRE); - m_sizerHyperlink->Add(m_hyperlink, 0, wxCENTRE); - m_sizerHyperlink->Add(m_fun, 0, wxCENTRE); - m_sizerHyperlink->Add(0, 0, 1, wxCENTRE); - m_sizerHyperlink->Layout(); + // relayout the sizer + GetSizer()->Layout(); +} + +void HyperlinkWidgetsPage::CreateHyperlinkLong(long style) +{ + style = (wxHL_DEFAULT_STYLE & ~wxHL_ALIGN_CENTRE)|style; + wxHyperlinkCtrl *hyp = new wxHyperlinkCtrl(this, + wxID_ANY, + wxT("This is a long hyperlink"), + wxT("www.wxwidgets.org"), + wxDefaultPosition, + wxDefaultSize, + style); + + // update sizer's child window + GetSizer()->Replace(m_hyperlinkLong, hyp, true); + + // update our pointer + delete m_hyperlinkLong; + m_hyperlinkLong = hyp; + + // relayout the sizer + GetSizer()->Layout(); } // ---------------------------------------------------------------------------- @@ -237,4 +299,30 @@ void HyperlinkWidgetsPage::OnButtonSetURL(wxCommandEvent& WXUNUSED(event)) CreateHyperlink(); } +void HyperlinkWidgetsPage::OnAlignment(wxCommandEvent& WXUNUSED(event)) +{ + long addstyle; + switch ( m_radioAlignMode->GetSelection() ) + { + default: + case Align_Max: + wxFAIL_MSG( _T("unknown alignment") ); + // fall through + + case Align_Left: + addstyle = wxHL_ALIGN_LEFT; + break; + + case Align_Centre: + addstyle = wxHL_ALIGN_CENTRE; + break; + + case Align_Right: + addstyle = wxHL_ALIGN_RIGHT; + break; + } + + CreateHyperlinkLong(addstyle); +} + #endif // wxUSE_HYPERLINKCTRL diff --git a/src/generic/hyperlink.cpp b/src/generic/hyperlink.cpp index fb245d32b2..9d96c5e296 100644 --- a/src/generic/hyperlink.cpp +++ b/src/generic/hyperlink.cpp @@ -62,8 +62,9 @@ BEGIN_EVENT_TABLE(wxHyperlinkCtrl, wxControl) EVT_LEFT_DOWN(wxHyperlinkCtrl::OnLeftDown) EVT_LEFT_UP(wxHyperlinkCtrl::OnLeftUp) EVT_RIGHT_UP(wxHyperlinkCtrl::OnRightUp) - EVT_ENTER_WINDOW(wxHyperlinkCtrl::OnEnterWindow) + EVT_MOTION(wxHyperlinkCtrl::OnMotion) EVT_LEAVE_WINDOW(wxHyperlinkCtrl::OnLeaveWindow) + EVT_SIZE(wxHyperlinkCtrl::OnSize) // for the context menu EVT_MENU(wxHYPERLINKCTRL_POPUP_COPY_ID, wxHyperlinkCtrl::OnPopUpCopy) @@ -76,6 +77,14 @@ bool wxHyperlinkCtrl::Create(wxWindow *parent, wxWindowID id, wxASSERT_MSG(!url.empty() || !label.empty(), wxT("Both URL and label are empty ?")); +#ifdef __WXDEBUG__ + int alignment = (int)((style & wxHL_ALIGN_LEFT) != 0) + + (int)((style & wxHL_ALIGN_CENTRE) != 0) + + (int)((style & wxHL_ALIGN_RIGHT) != 0); + wxASSERT_MSG(alignment == 1, + wxT("Specify exactly one align flag!")); +#endif + if (!wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name)) return false; @@ -90,9 +99,6 @@ bool wxHyperlinkCtrl::Create(wxWindow *parent, wxWindowID id, else SetLabel(label); - // by default the cursor to use in this window is wxCURSOR_HAND - SetCursor(wxCursor(wxCURSOR_HAND)); - m_rollover = false; m_clicking = false; m_visited = false; @@ -159,6 +165,24 @@ void wxHyperlinkCtrl::DoContextMenu(const wxPoint &pos) delete menuPopUp; } +wxRect wxHyperlinkCtrl::GetLabelRect() const +{ + // our best size is always the size of the label without borders + wxSize c(GetClientSize()), b(GetBestSize()); + wxPoint offset; + + // the label is always centered vertically + offset.y = (c.GetHeight()-b.GetHeight())/2; + + if (HasFlag(wxHL_ALIGN_CENTRE)) + offset.x = (c.GetWidth()-b.GetWidth())/2; + else if (HasFlag(wxHL_ALIGN_RIGHT)) + offset.x = c.GetWidth()-b.GetWidth(); + else if (HasFlag(wxHL_ALIGN_LEFT)) + offset.x = 0; + return wxRect(offset, b); +} + // ---------------------------------------------------------------------------- @@ -171,17 +195,21 @@ void wxHyperlinkCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) dc.SetFont(GetFont()); dc.SetTextForeground(GetForegroundColour()); dc.SetTextBackground(GetBackgroundColour()); - dc.DrawText(GetLabel(), 0, 0); + + dc.DrawText(GetLabel(), GetLabelRect().GetTopLeft()); } -void wxHyperlinkCtrl::OnLeftDown(wxMouseEvent& WXUNUSED(event)) +void wxHyperlinkCtrl::OnLeftDown(wxMouseEvent& event) { - m_clicking = true; + // the left click must start from the hyperlink rect + m_clicking = GetLabelRect().Inside(event.GetPosition()); } -void wxHyperlinkCtrl::OnLeftUp(wxMouseEvent& WXUNUSED(event)) +void wxHyperlinkCtrl::OnLeftUp(wxMouseEvent& event) { - if (!m_clicking) return; + // the click must be started and ended in the hyperlink rect + if (!m_clicking || !GetLabelRect().Inside(event.GetPosition())) + return; SetForegroundColour(m_visitedColour); m_visited = true; @@ -197,20 +225,40 @@ void wxHyperlinkCtrl::OnLeftUp(wxMouseEvent& WXUNUSED(event)) void wxHyperlinkCtrl::OnRightUp(wxMouseEvent& event) { if( GetWindowStyle() & wxHL_CONTEXTMENU ) - DoContextMenu(wxPoint(event.m_x, event.m_y)); + if ( GetLabelRect().Inside(event.GetPosition()) ) + DoContextMenu(wxPoint(event.m_x, event.m_y)); } -void wxHyperlinkCtrl::OnEnterWindow(wxMouseEvent& WXUNUSED(event)) +void wxHyperlinkCtrl::OnMotion(wxMouseEvent& event) { - SetForegroundColour(m_hoverColour); - m_rollover = true; - Refresh(); + wxRect textrc = GetLabelRect(); + + if (textrc.Inside(event.GetPosition())) + { + SetCursor(wxCursor(wxCURSOR_HAND)); + SetForegroundColour(m_hoverColour); + m_rollover = true; + Refresh(); + } + else if (m_rollover) + { + SetCursor(*wxSTANDARD_CURSOR); + SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour); + m_rollover = false; + Refresh(); + } } -void wxHyperlinkCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event)) +void wxHyperlinkCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event) ) { + // NB: when the label rect and the client size rect have the same + // height this function is indispensable to remove the "rollover" + // effect as the OnMotion() event handler could not be called + // in that case moving the mouse out of the label vertically... + if (m_rollover) { + SetCursor(*wxSTANDARD_CURSOR); SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour); m_rollover = false; Refresh(); @@ -229,4 +277,11 @@ void wxHyperlinkCtrl::OnPopUpCopy( wxCommandEvent& WXUNUSED(event) ) #endif // wxUSE_CLIPBOARD } +void wxHyperlinkCtrl::OnSize(wxSizeEvent& WXUNUSED(event)) +{ + // update the position of the label in the screen respecting + // the selected align flag + Refresh(); +} + #endif // wxUSE_HYPERLINKCTRL