X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1a78a6290510473b40a3f222030de64939886753..1759ff9e918d43734793c67328af21203924931f:/user/wxLayout/wxlwindow.cpp?ds=sidebyside diff --git a/user/wxLayout/wxlwindow.cpp b/user/wxLayout/wxlwindow.cpp index f95b20eb45..4331bd51bf 100644 --- a/user/wxLayout/wxlwindow.cpp +++ b/user/wxLayout/wxlwindow.cpp @@ -75,6 +75,7 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent) wxHSCROLL | wxVSCROLL | wxBORDER) { + SetStatusBar(NULL); // don't use statusbar m_Editable = false; m_doSendEvents = false; m_ViewStartX = 0; m_ViewStartY = 0; @@ -92,6 +93,7 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent) EnableScrolling(true,true); m_maxx = max.x; m_maxy = max.y; m_Selecting = false; + SetCursorVisibility(-1); SetCursor(wxCURSOR_IBEAM); SetDirty(); } @@ -105,6 +107,28 @@ wxLayoutWindow::~wxLayoutWindow() SetBackgroundBitmap(NULL); } +void +wxLayoutWindow::Clear(int family, + int size, + int style, + int weight, + int underline, + wxColour *fg, + wxColour *bg) +{ + GetLayoutList()->Clear(family,size,style,weight,underline,fg,bg); + SetBackgroundColour(GetLayoutList()->GetDefaults()->GetBGColour()); + ResizeScrollbars(true); + SetDirty(); + SetModified(false); + wxRect r; + int w,h; + r.x = r.y = 0; GetSize(&w,&h); + r.width = w; + r.height = h; + DoPaint(&r); +} + #ifdef __WXMSW__ long wxLayoutWindow::MSWGetDlgCode() @@ -121,7 +145,6 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) PrepareDC( dc ); SetFocus(); - wxPoint findPos; findPos.x = dc.DeviceToLogicalX(event.GetX()); findPos.y = dc.DeviceToLogicalY(event.GetY()); @@ -138,24 +161,55 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) bool found; wxLayoutObject *obj = m_llist->FindObjectScreen(dc, findPos, &cursorPos, &found); + wxLayoutObject::UserData *u = obj ? obj->GetUserData() : NULL; //has the mouse only been moved? if(eventId == WXLOWIN_MENU_MOUSEMOVE) { // found is only true if we are really over an object, not just // behind it - if(found && obj && obj->GetUserData() != NULL) + if(found && u && ! m_Selecting) { if(!m_HandCursor) SetCursor(wxCURSOR_HAND); m_HandCursor = TRUE; + if(m_StatusBar && m_StatusFieldLabel != -1) + { + const wxString &label = u->GetLabel(); + if(label.Length()) + m_StatusBar->SetStatusText(label, + m_StatusFieldLabel); + } } else { if(m_HandCursor) SetCursor(wxCURSOR_IBEAM); m_HandCursor = FALSE; + if(m_StatusBar && m_StatusFieldLabel != -1) + m_StatusBar->SetStatusText("", m_StatusFieldLabel); + } + if(event.LeftIsDown()) + { + if(! m_Selecting) + { + m_llist->StartSelection(); + m_Selecting = true; + DoPaint(FALSE); + } + else + { + m_llist->ContinueSelection(cursorPos); + DoPaint(FALSE); + } } + if(m_Selecting && ! event.LeftIsDown()) + { + m_llist->EndSelection(cursorPos); + m_Selecting = false; + DoPaint(FALSE); + } + if(u) u->DecRef(); return; } @@ -163,21 +217,29 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) if(obj && eventId == WXLOWIN_MENU_LCLICK) { m_llist->MoveCursorTo(cursorPos); + if(m_CursorVisibility == -1) + m_CursorVisibility = 1; ScrollToCursor(); - Refresh(); + DoPaint(FALSE); // DoPaint suppresses flicker under GTK } + if(!m_doSendEvents) // nothing to do + { + if(u) u->DecRef(); return; + } // only do the menu if activated, editable and not on a clickable object if(eventId == WXLOWIN_MENU_RCLICK && IsEditable() - && (! obj || (obj && obj->GetUserData() == NULL)) - ) + && (! obj || u == NULL)) { PopupMenu(m_PopupMenu, m_ClickPosition.x, m_ClickPosition.y); + if(u) u->DecRef(); return; } + + if(u) u->DecRef(); // find the object at this position if(obj) { @@ -194,179 +256,196 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) void wxLayoutWindow::OnChar(wxKeyEvent& event) { + int keyCode = event.KeyCode(); + #ifdef WXLAYOUT_DEBUG - if(event.KeyCode() == WXK_F1) + if(keyCode == WXK_F1) { m_llist->Debug(); return; } #endif - - long keyCode = event.KeyCode(); - if(m_Selecting && ! event.ShiftDown()) - { - m_llist->EndSelection(); - m_Selecting = false; - } - else - if(! m_Selecting && event.ShiftDown()) - { - switch(keyCode) - { - case WXK_UP: - case WXK_DOWN: - case WXK_RIGHT: - case WXK_LEFT: - case WXK_PRIOR: - case WXK_NEXT: - case WXK_HOME: - case WXK_END: - m_Selecting = true; - m_llist->StartSelection(); - break; - default: - ; - } - } - - if(!IsEditable()) // do nothing + + if(! m_Selecting && event.ShiftDown()) { switch(keyCode) { case WXK_UP: - m_llist->MoveCursorVertically(-1); - break; case WXK_DOWN: - m_llist->MoveCursorVertically(1); - break; + case WXK_RIGHT: + case WXK_LEFT: case WXK_PRIOR: - m_llist->MoveCursorVertically(-20); - break; case WXK_NEXT: - m_llist->MoveCursorVertically(20); + case WXK_HOME: + case WXK_END: + m_Selecting = true; + m_llist->StartSelection(); break; default: ; } - return; } + + // If needed, make cursor visible: + if(m_CursorVisibility == -1) + m_CursorVisibility = 1; - /* First, handle control keys */ - if(event.ControlDown() && ! event.AltDown()) + /* These two nested switches work like this: + The first one processes all non-editing keycodes, to move the + cursor, etc. It's default will process all keycodes causing + modifications to the buffer, but only if editing is allowed. + */ + switch(keyCode) { - switch(keyCode) + case WXK_RIGHT: + m_llist->MoveCursorHorizontally(1); + break; + case WXK_LEFT: + m_llist->MoveCursorHorizontally(-1); + break; + case WXK_UP: + m_llist->MoveCursorVertically(-1); + break; + case WXK_DOWN: + m_llist->MoveCursorVertically(1); + break; + case WXK_PRIOR: + m_llist->MoveCursorVertically(-20); + break; + case WXK_NEXT: + m_llist->MoveCursorVertically(20); + break; + case WXK_HOME: + m_llist->MoveCursorToBeginOfLine(); + break; + case WXK_END: + m_llist->MoveCursorToEndOfLine(); + break; + default: + if(keyCode == 'c' && event.ControlDown()) + Copy(); + if( IsEditable() ) { - case WXK_DELETE : - case 'd': - m_llist->Delete(1); - break; - case 'y': - m_llist->DeleteLines(1); - break; - case 'h': // like backspace - if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1); - break; - case 'u': - m_llist->DeleteToBeginOfLine(); - break; - case 'k': - m_llist->DeleteToEndOfLine(); - break; - case 'v': - Paste(); - break; + /* First, handle control keys */ + if(event.ControlDown() && ! event.AltDown()) + { + switch(keyCode) + { + case WXK_INSERT: + Copy(); + break; + case WXK_DELETE : + case 'd': + m_llist->Delete(1); + break; + case 'y': + m_llist->DeleteLines(1); + break; + case 'h': // like backspace + if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1); + break; + case 'u': + m_llist->DeleteToBeginOfLine(); + break; + case 'k': + m_llist->DeleteToEndOfLine(); + break; + case 'v': + Paste(); + break; + case 'c': + Copy(); + break; + case 'x': + Cut(); + break; #ifdef WXLAYOUT_DEBUG - case WXK_F1: - m_llist->SetFont(-1,-1,-1,-1,true); // underlined - break; + case WXK_F1: + m_llist->SetFont(-1,-1,-1,-1,true); // underlined + break; #endif - default: - ; - } - } - // ALT only: - else if( event.AltDown() && ! event.ControlDown() ) - { - switch(keyCode) - { - case WXK_DELETE: - case 'd': - m_llist->DeleteWord(); - break; - default: - ; - } - } - // no control keys: - else if ( ! event.AltDown() && ! event.ControlDown()) - { - switch(keyCode) - { - case WXK_RIGHT: - m_llist->MoveCursorHorizontally(1); - break; - case WXK_LEFT: - m_llist->MoveCursorHorizontally(-1); - break; - case WXK_UP: - m_llist->MoveCursorVertically(-1); - break; - case WXK_DOWN: - m_llist->MoveCursorVertically(1); - break; - case WXK_PRIOR: - m_llist->MoveCursorVertically(-20); - break; - case WXK_NEXT: - m_llist->MoveCursorVertically(20); - break; - case WXK_HOME: - m_llist->MoveCursorToBeginOfLine(); - break; - case WXK_END: - m_llist->MoveCursorToEndOfLine(); - break; - case WXK_INSERT: - if(event.ShiftDown()) - Paste(); - break; - case WXK_DELETE : - m_llist->Delete(1); - break; - case WXK_BACK: // backspace - if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1); - break; - case WXK_RETURN: - if(m_WrapMargin > 0) - m_llist->WrapLine(m_WrapMargin); - m_llist->LineBreak(); - break; - default: - if((!(event.ControlDown() || event.AltDown() || event.MetaDown())) - && (keyCode < 256 && keyCode >= 32) - ) + default: + ; + } + } + // ALT only: + else if( event.AltDown() && ! event.ControlDown() ) { - wxString tmp; - tmp += keyCode; - if(m_WrapMargin > 0 && isspace(keyCode)) - m_llist->WrapLine(m_WrapMargin); - m_llist->Insert(tmp); + switch(keyCode) + { + case WXK_DELETE: + case 'd': + m_llist->DeleteWord(); + break; + default: + ; + } } - break; + // no control keys: + else if ( ! event.AltDown() && ! event.ControlDown()) + { + switch(keyCode) + { + case WXK_INSERT: + if(event.ShiftDown()) + Paste(); + break; + case WXK_DELETE : + if(event.ShiftDown()) + Cut(); + else + m_llist->Delete(1); + break; + case WXK_BACK: // backspace + if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1); + break; + case WXK_RETURN: + if(m_WrapMargin > 0) + m_llist->WrapLine(m_WrapMargin); + m_llist->LineBreak(); + break; + default: + if((!(event.ControlDown() || event.AltDown() || event.MetaDown())) + && (keyCode < 256 && keyCode >= 32) + ) + { + wxString tmp; + tmp += keyCode; + if(m_WrapMargin > 0 && isspace(keyCode)) + m_llist->WrapLine(m_WrapMargin); + m_llist->Insert(tmp); + } + break; + } + } + SetDirty(); + SetModified(); + }// if(IsEditable()) + }// first switch() + if(m_Selecting) + { + if(event.ShiftDown()) + m_llist->ContinueSelection(); + else + { + m_llist->EndSelection(); + m_Selecting = false; } } - SetDirty(); - SetModified(); + ScrollToCursor(); wxRect r = *m_llist->GetUpdateRect(); - Refresh( FALSE, &r); + DoPaint(&r); } void wxLayoutWindow::OnKeyUp(wxKeyEvent& event) { if(event.KeyCode() == WXK_SHIFT && m_llist->IsSelecting()) + { m_llist->EndSelection(); + m_Selecting = false; + } event.Skip(); } @@ -384,6 +463,8 @@ wxLayoutWindow::ScrollToCursor(void) GetScrollPixelsPerUnit(&dx, &dy); x0 *= dx; y0 *= dy; + WXLO_DEBUG(("ScrollToCursor: ViewStart is %d/%d", x0, y0)); + // Get the size of the visible window: GetClientSize(&x1,&y1); wxASSERT(x1 > 0); @@ -448,14 +529,19 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) if(x1 > m_maxx) m_maxx = x1; if(y1 > m_maxy) m_maxy = y1; - WXLO_DEBUG(("Update rect: %ld,%ld / %ld,%ld", - updateRect->x, updateRect->y, - updateRect->x+updateRect->width, - updateRect->y+updateRect->height)); + if(updateRect) + { + WXLO_DEBUG(("Update rect: %ld,%ld / %ld,%ld", + updateRect->x, updateRect->y, + updateRect->x+updateRect->width, + updateRect->y+updateRect->height)); + } if(IsDirty()) + { + m_llist->Layout(dc); ResizeScrollbars(); - + } /* Check whether the window has grown, if so, we need to reallocate the bitmap to be larger. */ if(x1 > m_bitmapSize.x || y1 > m_bitmapSize.y) @@ -498,10 +584,15 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) /* This is the important bit: we tell the list to draw itself: */ - WXLO_DEBUG(("Update rect: %ld,%ld / %ld,%ld", - updateRect->x, updateRect->y, - updateRect->x+updateRect->width, - updateRect->y+updateRect->height)); +#if WXLO_DEBUG_URECT + if(updateRect) + { + WXLO_DEBUG(("Update rect: %ld,%ld / %ld,%ld", + updateRect->x, updateRect->y, + updateRect->x+updateRect->width, + updateRect->y+updateRect->height)); + } +#endif // Device origins on the memDC are suspect, we translate manually // with the translate parameter of Draw(). @@ -513,8 +604,11 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) // update rectangle (although they are drawn on the memDC, this is // needed to erase it): m_llist->InvalidateUpdateRect(); - if(IsEditable()) //we draw the cursor - m_llist->DrawCursor(*m_memDC,m_HaveFocus,offset); + if(m_CursorVisibility == 1) + m_llist->DrawCursor(*m_memDC, + m_HaveFocus && IsEditable(), // draw a thick + // cursor for editable windows with focus + offset); // Now copy everything to the screen: #if 0 @@ -544,6 +638,12 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) ResetDirty(); m_ScrollToCursor = false; + if(m_StatusBar && m_StatusFieldCursor != -1) + { + wxString label; + label.Printf(_("L:%d C:%d"), m_llist->GetCursorPos().x+1, m_llist->GetCursorPos().y+1); + m_StatusBar->SetStatusText(label, m_StatusFieldCursor); + } } // change the range and position of scrollbars @@ -551,7 +651,9 @@ void wxLayoutWindow::ResizeScrollbars(bool exact) { wxPoint max = m_llist->GetSize(); - + + WXLO_DEBUG(("ResizeScrollbars: GetSize: %ld, %ld", (long int)max.x, + (long int) max.y)); if(max.x > m_maxx || max.y > m_maxy || max.x > m_maxx-WXLO_ROFFSET || max.y > m_maxy-WXLO_BOFFSET || exact) @@ -571,16 +673,29 @@ wxLayoutWindow::ResizeScrollbars(bool exact) void wxLayoutWindow::Paste(void) { - wxString text; // Read some text if (wxTheClipboard->Open()) { - wxTextDataObject data; - if (wxTheClipboard->IsSupported( data.GetFormat() )) +#if wxUSE_PRIVATE_CLIPBOARD_FORMAT + wxLayoutDataObject wxldo; + if (wxTheClipboard->IsSupported( wxldo.GetFormat() )) { - wxTheClipboard->GetData(&data); - text += data.GetText(); + wxTheClipboard->GetData(&wxldo); + { + } + //FIXME: missing functionality m_llist->Insert(wxldo.GetList()); } + else +#endif + { + wxTextDataObject data; + if (wxTheClipboard->IsSupported( data.GetFormat() )) + { + wxTheClipboard->GetData(&data); + wxString text = data.GetText(); + wxLayoutImportText( m_llist, text); + } + } wxTheClipboard->Close(); } #if 0 @@ -593,16 +708,24 @@ wxLayoutWindow::Paste(void) text += tmp_tctrl.GetValue(); } #endif - wxLayoutImportText( m_llist, text); } bool -wxLayoutWindow::Copy(void) +wxLayoutWindow::Copy(bool invalidate) { - wxLayoutList *llist = m_llist->GetSelection(); + // Calling GetSelection() will automatically do an EndSelection() + // on the list, but we need to take a note of it, too: + if(m_Selecting) + { + m_Selecting = false; + m_llist->EndSelection(); + } + + wxLayoutDataObject wldo; + wxLayoutList *llist = m_llist->GetSelection(&wldo, invalidate); if(! llist) return FALSE; - + // Export selection as text: wxString text; wxLayoutExportObject *export; wxLayoutExportStatus status(llist); @@ -613,18 +736,66 @@ wxLayoutWindow::Copy(void) delete export; } delete llist; + + // The exporter always appends a newline, so we chop it off if it + // is there: + { + size_t len = text.Length(); + if(len > 2 && text[len-2] == '\r') // Windows + text = text.Mid(0,len-2); + else if(len > 1 && text[len-1] == '\n') + text = text.Mid(0,len-1); + } - // Read some text + if (wxTheClipboard->Open()) { wxTextDataObject *data = new wxTextDataObject( text ); bool rc = wxTheClipboard->SetData( data ); +#if wxUSE_PRIVATE_CLIPBOARD_FORMAT + rc |= wxTheClipboard->AddData( &wldo ); +#endif wxTheClipboard->Close(); return rc; } return FALSE; } +bool +wxLayoutWindow::Cut(void) +{ + if(Copy(false)) // do not invalidate selection after copy + { + m_llist->DeleteSelection(); + return TRUE; + } + else + return FALSE; +} +bool +wxLayoutWindow::Find(const wxString &needle, + wxPoint * fromWhere) +{ + wxPoint found; + + if(fromWhere == NULL) + found = m_llist->FindText(needle, m_llist->GetCursorPos()); + else + found = m_llist->FindText(needle, *fromWhere); + if(found.x != -1) + { + if(fromWhere) + { + *fromWhere = found; + fromWhere->x ++; + } + m_llist->MoveCursorTo(found); + ScrollToCursor(); + return true; + } + return false; +} + wxMenu * wxLayoutWindow::MakeFormatMenu() { @@ -679,12 +850,12 @@ void wxLayoutWindow::OnSetFocus(wxFocusEvent &ev) { m_HaveFocus = true; -//FIXME DoPaint(); // to repaint the cursor +//FIXME: need argument DoPaint(); // to repaint the cursor } void wxLayoutWindow::OnKillFocus(wxFocusEvent &ev) { m_HaveFocus = false; -//FIXME DoPaint(); // to repaint the cursor +//FIXME: need argument DoPaint(); // to repaint the cursor }