]> git.saurik.com Git - wxWidgets.git/blobdiff - src/html/htmlwin.cpp
Added support for delayed deactivation of windows (for MDI)
[wxWidgets.git] / src / html / htmlwin.cpp
index a31d540ccf873cdad70e01c10ad0718d50784747..d6fe4c8e0220de3c22db33fbb5420b6fd8401468 100644 (file)
@@ -33,6 +33,7 @@
 #include "wx/html/htmlproc.h"
 #include "wx/list.h"
 #include "wx/clipbrd.h"
+#include "wx/dataobj.h"
 #include "wx/timer.h"
 #include "wx/dcmemory.h"
 
@@ -109,7 +110,8 @@ void wxHtmlWinAutoScrollTimer::Notify()
         }
     }
 }
-#endif
+
+#endif // wxUSE_CLIPBOARD
 
 
 
@@ -173,7 +175,8 @@ void wxHtmlWindow::Init()
     m_makingSelection = false;
 #if wxUSE_CLIPBOARD
     m_timerAutoScroll = NULL;
-#endif
+    m_lastDoubleClick = 0;
+#endif // wxUSE_CLIPBOARD
     m_backBuffer = NULL;
 }
 
@@ -195,7 +198,7 @@ wxHtmlWindow::~wxHtmlWindow()
 {
 #if wxUSE_CLIPBOARD
     StopAutoScrolling();
-#endif
+#endif // wxUSE_CLIPBOARD
     HistoryClear();
 
     if (m_Cell) delete m_Cell;
@@ -689,8 +692,6 @@ void wxHtmlWindow::AddProcessor(wxHtmlProcessor *processor)
 
 wxList wxHtmlWindow::m_Filters;
 wxHtmlFilter *wxHtmlWindow::m_DefaultFilter = NULL;
-wxCursor *wxHtmlWindow::s_cur_hand = NULL;
-wxCursor *wxHtmlWindow::s_cur_arrow = NULL;
 wxHtmlProcessorList *wxHtmlWindow::m_GlobalProcessors = NULL;
 
 void wxHtmlWindow::CleanUpStatics()
@@ -699,8 +700,6 @@ void wxHtmlWindow::CleanUpStatics()
     m_Filters.DeleteContents(TRUE);
     m_Filters.Clear();
     wxDELETE(m_GlobalProcessors);
-    wxDELETE(s_cur_hand);
-    wxDELETE(s_cur_arrow);
 }
 
 
@@ -719,7 +718,7 @@ bool wxHtmlWindow::IsSelectionEnabled() const
     return false;
 #endif
 }
-    
+
 
 #if wxUSE_CLIPBOARD
 wxString wxHtmlWindow::SelectionToText()
@@ -749,22 +748,35 @@ wxString wxHtmlWindow::SelectionToText()
     return text;
 }
 
+#endif // wxUSE_CLIPBOARD
+
 void wxHtmlWindow::CopySelection(ClipboardType t)
 {
+#if wxUSE_CLIPBOARD
     if ( m_selection )
     {
+#ifdef __UNIX__
         wxTheClipboard->UsePrimarySelection(t == Primary);
-        wxString txt(SelectionToText());
+#else // !__UNIX__
+        // Primary selection exists only under X11, so don't do anything under
+        // the other platforms when we try to access it
+        //
+        // TODO: this should be abstracted at wxClipboard level!
+        if ( t == Primary )
+            return;
+#endif // __UNIX__/!__UNIX__
+
         if ( wxTheClipboard->Open() )
         {
+            const wxString txt(SelectionToText());
             wxTheClipboard->SetData(new wxTextDataObject(txt));
             wxTheClipboard->Close();
             wxLogTrace(_T("wxhtmlselection"),
                        _("Copied to clipboard:\"%s\""), txt.c_str());
         }
     }
+#endif // wxUSE_CLIPBOARD
 }
-#endif
 
 
 void wxHtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link)
@@ -807,13 +819,13 @@ void wxHtmlWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
     wxMemoryDC dcm;
     if ( !m_backBuffer )
         m_backBuffer = new wxBitmap(sz.x, sz.y);
-    dcm.SelectObject(*m_backBuffer);    
+    dcm.SelectObject(*m_backBuffer);
     dcm.SetBackground(wxBrush(GetBackgroundColour(), wxSOLID));
     dcm.Clear();
     PrepareDC(dcm);
     dcm.SetMapMode(wxMM_TEXT);
     dcm.SetBackgroundMode(wxTRANSPARENT);
-    
+
     wxHtmlRenderingInfo rinfo;
     wxDefaultHtmlRenderingStyle rstyle;
     rinfo.SetSelection(m_selection);
@@ -847,7 +859,7 @@ void wxHtmlWindow::OnSize(wxSizeEvent& event)
                          m_selection->GetToCell());
         m_selection->ClearPrivPos();
     }
-    
+
     Refresh();
 }
 
@@ -859,20 +871,32 @@ void wxHtmlWindow::OnMouseMove(wxMouseEvent& event)
 
 void wxHtmlWindow::OnMouseDown(wxMouseEvent& event)
 {
+#if wxUSE_CLIPBOARD
     if ( event.LeftDown() && IsSelectionEnabled() )
     {
-        m_makingSelection = true;
-            
-        if ( m_selection )
+        const long TRIPLECLICK_LEN = 200; // 0.2 sec after doubleclick
+        if ( wxGetLocalTimeMillis() - m_lastDoubleClick <= TRIPLECLICK_LEN )
         {
-            wxDELETE(m_selection);
-            Refresh();
+            SelectLine(CalcUnscrolledPosition(event.GetPosition()));
+
+            CopySelection();
         }
-        m_tmpSelFromPos = CalcUnscrolledPosition(event.GetPosition());
-        m_tmpSelFromCell = NULL;
+        else
+        {
+            m_makingSelection = true;
 
-        CaptureMouse();
+            if ( m_selection )
+            {
+                wxDELETE(m_selection);
+                Refresh();
+            }
+            m_tmpSelFromPos = CalcUnscrolledPosition(event.GetPosition());
+            m_tmpSelFromCell = NULL;
+
+            CaptureMouse();
+        }
     }
+#endif // wxUSE_CLIPBOARD
 }
 
 void wxHtmlWindow::OnMouseUp(wxMouseEvent& event)
@@ -886,25 +910,24 @@ void wxHtmlWindow::OnMouseUp(wxMouseEvent& event)
         // did the user move the mouse far enough from starting point?
         if ( m_selection )
         {
-#ifdef __UNIX__
             CopySelection(Primary);
-#endif
+
             // we don't want mouse up event that ended selecting to be
             // handled as mouse click and e.g. follow hyperlink:
             return;
         }
     }
-#endif
-    
+#endif // wxUSE_CLIPBOARD
+
     SetFocus();
     if ( m_Cell )
     {
         wxPoint pos = CalcUnscrolledPosition(event.GetPosition());
         wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
 
-        // VZ: is it possible that we don't find anything at all?
-        // VS: yes. FindCellByPos returns terminal cell and
-        //     containers may have empty borders
+        // check is needed because FindCellByPos returns terminal cell and
+        // containers may have empty borders -- in this case NULL will be
+        // returned
         if ( cell )
             OnCellClicked(cell, pos.x, pos.y, event);
     }
@@ -914,12 +937,6 @@ void wxHtmlWindow::OnMouseUp(wxMouseEvent& event)
 
 void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
 {
-    if (s_cur_hand == NULL)
-    {
-        s_cur_hand = new wxCursor(wxCURSOR_HAND);
-        s_cur_arrow = new wxCursor(wxCURSOR_ARROW);
-    }
-
     if (m_tmpMouseMoved && (m_Cell != NULL))
     {
         int xc, yc, x, y;
@@ -976,9 +993,9 @@ void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
 
             // NB: it may *rarely* happen that the code above didn't find one
             //     of the cells, e.g. if wxHtmlWindow doesn't contain any
-            //     visible cells. 
+            //     visible cells.
             if ( selcell && m_tmpSelFromCell )
-            {                
+            {
                 if ( !m_selection )
                 {
                     // start selecting only if mouse movement was big enough
@@ -1006,25 +1023,31 @@ void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
                 }
             }
         }
-        
+
         // handle cursor and status bar text changes:
         if ( cell != m_tmpLastCell )
         {
             wxHtmlLinkInfo *lnk = cell ? cell->GetLink(x, y) : NULL;
+            wxCursor cur;
+            if (cell)
+                cur = cell->GetCursor();
+            else
+                cur = *wxSTANDARD_CURSOR;
+            SetCursor(cur);
 
             if (lnk != m_tmpLastLink)
             {
                 if (lnk == NULL)
                 {
-                    SetCursor(*s_cur_arrow);
                     if (m_RelatedStatusBar != -1)
-                        m_RelatedFrame->SetStatusText(wxEmptyString, m_RelatedStatusBar);
+                        m_RelatedFrame->SetStatusText(wxEmptyString,
+                                                      m_RelatedStatusBar);
                 }
                 else
                 {
-                    SetCursor(*s_cur_hand);
                     if (m_RelatedStatusBar != -1)
-                        m_RelatedFrame->SetStatusText(lnk->GetHref(), m_RelatedStatusBar);
+                        m_RelatedFrame->SetStatusText(lnk->GetHref(),
+                                                      m_RelatedStatusBar);
                 }
                 m_tmpLastLink = lnk;
             }
@@ -1123,13 +1146,12 @@ void wxHtmlWindow::OnMouseLeave(wxMouseEvent& event)
 
 void wxHtmlWindow::OnKeyUp(wxKeyEvent& event)
 {
-    if ( event.GetKeyCode() == 'C' && event.ControlDown() )
+    if ( IsSelectionEnabled() &&
+         event.GetKeyCode() == 'C' && event.ControlDown() )
     {
         if ( m_selection )
             CopySelection();
     }
-    else
-        event.Skip();
 }
 
 void wxHtmlWindow::OnCopy(wxCommandEvent& event)
@@ -1137,7 +1159,88 @@ void wxHtmlWindow::OnCopy(wxCommandEvent& event)
     if ( m_selection )
         CopySelection();
 }
-#endif
+
+void wxHtmlWindow::OnDoubleClick(wxMouseEvent& event)
+{
+    // select word under cursor:
+    if ( IsSelectionEnabled() )
+    {
+        SelectWord(CalcUnscrolledPosition(event.GetPosition()));
+
+        CopySelection(Primary);
+
+        m_lastDoubleClick = wxGetLocalTimeMillis();
+    }
+    else
+        event.Skip();
+}
+
+void wxHtmlWindow::SelectWord(const wxPoint& pos)
+{
+    wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
+    if ( cell )
+    {
+        delete m_selection;
+        m_selection = new wxHtmlSelection();
+        m_selection->Set(cell, cell);
+        RefreshRect(wxRect(CalcScrolledPosition(cell->GetAbsPos()),
+                           wxSize(cell->GetWidth(), cell->GetHeight())));
+    }
+}
+
+void wxHtmlWindow::SelectLine(const wxPoint& pos)
+{
+    wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
+    if ( cell )
+    {
+        // We use following heuristic to find a "line": let the line be all
+        // cells in same container as the cell under mouse cursor that are
+        // neither completely above nor completely bellow the clicked cell
+        // (i.e. are likely to be words positioned on same line of text).
+
+        int y1 = cell->GetAbsPos().y;
+        int y2 = y1 + cell->GetHeight();
+        int y;
+        const wxHtmlCell *c;
+        const wxHtmlCell *before = NULL;
+        const wxHtmlCell *after = NULL;
+
+        // find last cell of line:
+        for ( c = cell->GetNext(); c; c = c->GetNext())
+        {
+            y = c->GetAbsPos().y;
+            if ( y + c->GetHeight() > y1 && y < y2 )
+                after = c;
+            else
+                break;
+        }
+        if ( !after )
+            after = cell;
+
+        // find first cell of line:
+        for ( c = cell->GetParent()->GetFirstChild();
+                c && c != cell; c = c->GetNext())
+        {
+            y = c->GetAbsPos().y;
+            if ( y + c->GetHeight() > y1 && y < y2 )
+            {
+                if ( ! before )
+                    before = c;
+            }
+            else
+                before = NULL;
+        }
+        if ( !before )
+            before = cell;
+
+        delete m_selection;
+        m_selection = new wxHtmlSelection();
+        m_selection->Set(before, after);
+
+        Refresh();
+    }
+}
+#endif // wxUSE_CLIPBOARD
 
 
 
@@ -1155,11 +1258,12 @@ BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow)
     EVT_ERASE_BACKGROUND(wxHtmlWindow::OnEraseBackground)
     EVT_PAINT(wxHtmlWindow::OnPaint)
 #if wxUSE_CLIPBOARD
+    EVT_LEFT_DCLICK(wxHtmlWindow::OnDoubleClick)
     EVT_ENTER_WINDOW(wxHtmlWindow::OnMouseEnter)
     EVT_LEAVE_WINDOW(wxHtmlWindow::OnMouseLeave)
     EVT_KEY_UP(wxHtmlWindow::OnKeyUp)
     EVT_MENU(wxID_COPY, wxHtmlWindow::OnCopy)
-#endif
+#endif // wxUSE_CLIPBOARD
 END_EVENT_TABLE()
 
 
@@ -1187,4 +1291,5 @@ IMPLEMENT_DYNAMIC_CLASS(wxHtmlWinModule, wxModule)
 #include "wx/html/forcelnk.h"
 FORCE_WXHTML_MODULES()
 
-#endif
+#endif // wxUSE_HTML
+