]> git.saurik.com Git - wxWidgets.git/commitdiff
added hyperlink alignment flags (patch 1537043)
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 10 Sep 2006 23:57:26 +0000 (23:57 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 10 Sep 2006 23:57:26 +0000 (23:57 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41153 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/latex/wx/hyperlink.tex
include/wx/hyperlink.h
samples/widgets/hyperlnk.cpp
src/generic/hyperlink.cpp

index 4c0c8df4a56c7a400c48aaaebaa7a5e508860bbb..0b252abfa020adbb7a5df7b205bce3e42637d272 100644 (file)
@@ -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}.
index cfbed46e96e5842fd5db98e6c5b16bb14bee4c72..c7e4ac4546ee3cf54e97f71021aec1a855b95f17 100644 (file)
 // ----------------------------------------------------------------------------
 
 #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
 
index 3c2295b539e951564645d9525e8c2389cff5df95..f1331d10c98660e4c94c06b8be36b54a7fcbcd9d 100644 (file)
@@ -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("&centre"),
+        _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
index fb245d32b22002bed8890b49a244711d0a6c389d..9d96c5e2965ca1b0cd3b4419022808a73c6f0177 100644 (file)
@@ -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