diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index b1843d54dd..d3a5f2f5c9 100644 --- a/src/richtext/richtextbuffer.cpp +++ b/src/richtext/richtextbuffer.cpp @@ -464,6 +464,7 @@ int wxRichTextFloatCollector::HitTestFloat(const wxRichTextFloatRectMapArray& ar textPosition = array[i]->anchor->GetRange().GetStart(); * obj = array[i]->anchor; + * contextObj = array[i]->anchor->GetParentContainer(); if (pt.x > (pt.x + pt.x + size.x) / 2) return wxRICHTEXT_HITTEST_BEFORE; else @@ -5218,7 +5219,30 @@ bool wxRichTextParagraph::Layout(wxDC& dc, wxRichTextDrawingContext& context, co // Substract -1 because the last position is always the end-paragraph position. if (lastCompletedEndPos <= GetRange().GetEnd()-1) { - currentPosition.x = (lineCount == 0 ? startPositionFirstLine : startPositionSubsequentLines); + int startOffset = (lineCount == 0 ? startPositionFirstLine : startPositionSubsequentLines); + availableRect = wxRect(rect.x + startOffset, rect.y + currentPosition.y, + rect.width - startOffset - rightIndent, rect.height); + + // Take into account floating objects for the last line + if (wxRichTextBuffer::GetFloatingLayoutMode() && collector) + { + wxRect floatAvailableRect = collector->GetAvailableRect(rect.y + currentPosition.y, rect.y + currentPosition.y + lineHeight); + + // Adjust availableRect to the space that is available when taking floating objects into account. + + if (floatAvailableRect.x + startOffset > availableRect.x) + { + int newX = floatAvailableRect.x + startOffset; + int newW = availableRect.width - (newX - availableRect.x); + availableRect.x = newX; + availableRect.width = newW; + } + + if (floatAvailableRect.width < availableRect.width) + availableRect.width = floatAvailableRect.width; + } + + currentPosition.x = availableRect.x - rect.x; wxRichTextLine* line = AllocateLine(lineCount); diff --git a/src/richtext/richtextctrl.cpp b/src/richtext/richtextctrl.cpp index 09d5c1b3d9..7ff2b18773 100644 --- a/src/richtext/richtextctrl.cpp +++ b/src/richtext/richtextctrl.cpp @@ -621,23 +621,35 @@ void wxRichTextCtrl::OnLeftClick(wxMouseEvent& event) { wxRichTextParagraphLayoutBox* oldFocusObject = GetFocusObject(); wxRichTextParagraphLayoutBox* container = wxDynamicCast(contextObj, wxRichTextParagraphLayoutBox); + bool needsCaretSet = false; if (container && container != GetFocusObject() && container->AcceptsFocus()) { SetFocusObject(container, false /* don't set caret position yet */); + needsCaretSet = true; } m_dragging = true; CaptureMouse(); - long oldCaretPos = m_caretPosition; - - SetCaretPositionAfterClick(container, position, hit); - - // For now, don't handle shift-click when we're selecting multiple objects. - if (event.ShiftDown() && GetFocusObject() == oldFocusObject && m_selectionState == wxRichTextCtrlSelectionState_Normal) - ExtendSelection(oldCaretPos, m_caretPosition, wxRICHTEXT_SHIFT_DOWN); + // Don't change the caret position if we clicked on a floating objects such as an image, + // unless we changed the focus object. + if (wxRichTextBuffer::GetFloatingLayoutMode() && hitObj && hitObj->IsFloating() && !hitObj->AcceptsFocus()) + { + if (needsCaretSet) + SetInsertionPoint(0); + } else - SelectNone(); + { + long oldCaretPos = m_caretPosition; + + SetCaretPositionAfterClick(container, position, hit); + + // For now, don't handle shift-click when we're selecting multiple objects. + if (event.ShiftDown() && GetFocusObject() == oldFocusObject && m_selectionState == wxRichTextCtrlSelectionState_Normal) + ExtendSelection(oldCaretPos, m_caretPosition, wxRICHTEXT_SHIFT_DOWN); + else + SelectNone(); + } } event.Skip(); @@ -678,20 +690,30 @@ void wxRichTextCtrl::OnLeftUp(wxMouseEvent& event) int hit = GetBuffer().HitTest(dc, context, GetUnscaledPoint(event.GetLogicalPosition(dc)), position, & hitObj, & contextObj, wxRICHTEXT_HITTEST_HONOUR_ATOMIC); wxRichTextParagraphLayoutBox* oldFocusObject = GetFocusObject(); wxRichTextParagraphLayoutBox* container = wxDynamicCast(contextObj, wxRichTextParagraphLayoutBox); + bool needsCaretSet = false; if (container && container != GetFocusObject() && container->AcceptsFocus()) { SetFocusObject(container, false /* don't set caret position yet */); + needsCaretSet = true; } - long oldCaretPos = m_caretPosition; - - SetCaretPositionAfterClick(container, position, hit); - - // For now, don't handle shift-click when we're selecting multiple objects. - if (event.ShiftDown() && GetFocusObject() == oldFocusObject && m_selectionState == wxRichTextCtrlSelectionState_Normal) - ExtendSelection(oldCaretPos, m_caretPosition, wxRICHTEXT_SHIFT_DOWN); + if (wxRichTextBuffer::GetFloatingLayoutMode() && hitObj && hitObj->IsFloating() && !hitObj->AcceptsFocus()) + { + if (needsCaretSet) + SetInsertionPoint(0); + } else - SelectNone(); + { + long oldCaretPos = m_caretPosition; + + SetCaretPositionAfterClick(container, position, hit); + + // For now, don't handle shift-click when we're selecting multiple objects. + if (event.ShiftDown() && GetFocusObject() == oldFocusObject && m_selectionState == wxRichTextCtrlSelectionState_Normal) + ExtendSelection(oldCaretPos, m_caretPosition, wxRICHTEXT_SHIFT_DOWN); + else + SelectNone(); + } } #endif @@ -1012,7 +1034,7 @@ void wxRichTextCtrl::OnRightClick(wxMouseEvent& event) } /// Left-double-click -void wxRichTextCtrl::OnLeftDClick(wxMouseEvent& WXUNUSED(event)) +void wxRichTextCtrl::OnLeftDClick(wxMouseEvent& event) { wxRichTextEvent cmdEvent( wxEVT_RICHTEXT_LEFT_DCLICK, @@ -1023,7 +1045,45 @@ void wxRichTextCtrl::OnLeftDClick(wxMouseEvent& WXUNUSED(event)) if (!GetEventHandler()->ProcessEvent(cmdEvent)) { - SelectWord(GetCaretPosition()+1); + bool okToSelectWord = true; + // Don't try to select a word if we clicked on a floating objects such as an image. + // Instead, select or deselect the object. + if (wxRichTextBuffer::GetFloatingLayoutMode()) + { + wxClientDC dc(this); + PrepareDC(dc); + dc.SetFont(GetFont()); + + long position = 0; + wxPoint logicalPt = event.GetLogicalPosition(dc); + wxRichTextObject* hitObj = NULL; + wxRichTextObject* contextObj = NULL; + wxRichTextDrawingContext context(& GetBuffer()); + int hit = GetFocusObject()->HitTest(dc, context, GetUnscaledPoint(logicalPt), position, & hitObj, & contextObj, wxRICHTEXT_HITTEST_HONOUR_ATOMIC); + wxUnusedVar(hit); + if (hitObj && hitObj->IsFloating() && !hitObj->AcceptsFocus()) + { + if ((GetFocusObject() == m_selection.GetContainer()) && m_selection.WithinSelection(hitObj->GetRange().GetStart())) + { + } + else + { + int from = hitObj->GetRange().GetStart(); + int to = hitObj->GetRange().GetStart()+1; + + wxRichTextSelection oldSelection = m_selection; + m_selectionAnchor = from-1; + m_selectionAnchorObject = NULL; + m_selection.Set(wxRichTextRange(from, to-1), GetFocusObject()); + RefreshForSelectionChange(oldSelection, m_selection); + } + okToSelectWord = false; + } + } + if (okToSelectWord) + { + SelectWord(GetCaretPosition()+1); + } } } @@ -3580,7 +3640,7 @@ int wxRichTextCtrl::PrepareContextMenu(wxMenu* menu, const wxPoint& pt, bool add else { if (addPropertyCommands) - m_contextMenuPropertiesInfo.AddItems(this, GetFocusObject(), NULL); + m_contextMenuPropertiesInfo.AddItems(this, GetFocusObject(), hitObj); } } else @@ -4540,6 +4600,26 @@ bool wxRichTextCtrl::RefreshForSelectionChange(const wxRichTextSelection& oldSel pt2.x = 0; pt2.y = wxMin(clientSize.y, pt2.y); + // Take into account any floating objects within the selection + if (wxRichTextBuffer::GetFloatingLayoutMode() && GetFocusObject()->GetFloatingObjectCount() > 0) + { + wxRichTextObjectList floatingObjects; + GetFocusObject()->GetFloatingObjects(floatingObjects); + wxRichTextObjectList::compatibility_iterator node = floatingObjects.GetFirst(); + while (node) + { + wxRichTextObject* obj = node->GetData(); + if (obj->GetRange().GetStart() >= firstPos && obj->GetRange().GetStart() <= lastPos) + { + wxPoint pt1Obj = GetPhysicalPoint(GetScaledPoint(obj->GetPosition())); + wxPoint pt2Obj = GetPhysicalPoint(GetScaledPoint(obj->GetPosition())) + wxPoint(0, (int) (0.5 + obj->GetCachedSize().y * GetScale())); + pt1.y = wxMin(pt1.y, pt1Obj.y); + pt2.y = wxMax(pt2.y, pt2Obj.y); + } + node = node->GetNext(); + } + } + wxRect rect(pt1, wxSize(clientSize.x, pt2.y - pt1.y)); RefreshRect(rect, false); }