void Canvas::set_zoom(int zoom, wxPoint center) { { /* Overpaint old image */ wxClientDC dc(this); wxPen pen( *wxLIGHT_GREY ); wxBrush brush( *wxLIGHT_GREY ); dc.SetPen( pen ); dc.SetBrush( brush ); dc.DrawRectangle( canvas_coords( wxRect(0, 0, contents->GetWidth(), contents->GetHeight())) ); } if ( center == wxDefaultPosition ) { int xl, yl, xs, ys, xr, yr; GetViewStart( &xl, &yl ); GetScrollPixelsPerUnit( &xr, &yr ); GetClientSize( &xs, &ys ); center.x = xl*xr + xs / 2; center.y = yl*yr + ys / 2; center = image_coords( wxRect( center, wxSize(1,1) ) ).GetTopLeft(); } if ( zoom < 0 ) { zoom_out_level = -zoom+1; zoom_in_level = 1; } else { zoom_out_level = 1; zoom_in_level = zoom+1; } if ( zcl ) zcl->zoom_changed( zoom ); wxSize new_size( contents->GetWidth(), contents->GetHeight() ); SetVirtualSize( canvas_coords( new_size ).GetSize() ); int xr, yr; GetScrollPixelsPerUnit( &xr, &yr ); wxRect viewport = get_visible_region(); /* Transform center to new scroll coordinates. */ wxPoint top_left = viewport.CenterIn( canvas_coords( wxRect( center, wxSize(1,1) ) ) ).GetTopLeft(); Scroll( top_left.x / xr, top_left.y / yr ); wxClientDC dc(this); DoPrepareDC( dc ); wxRect canvas_region = get_visible_region(); wxBitmap bitmap = zoomed_bitmap_for_canvas_region( canvas_region ); dc.DrawBitmap( bitmap, canvas_region.GetTopLeft() ); }
/// Get the overall rect of the given item bool InstanceCtrl::GetItemRect( VisualCoord item, wxRect& rect, bool view_relative ) { if (item.groupIndex < GetCount()) { int row, col; if (!GetRowCol(item, row, col)) return false; GroupVisual & gv = m_groups[item.groupIndex]; wxSize bsz = GetWindowBorderSize(); int x = col * (m_itemWidth + m_spacing) + m_spacing + bsz.GetWidth() / 2; int y = gv.y_position + gv.row_ys[row] + m_spacing; if (view_relative) { int startX, startY; int xppu, yppu; GetScrollPixelsPerUnit(& xppu, & yppu); GetViewStart(& startX, & startY); x = x - startX * xppu; y = y - startY * yppu; } rect.x = x; rect.y = y; rect.width = m_itemWidth; rect.height = GetItemHeight(item); return true; } return false; }
void WinEDA_DrawPanel::SetBoundaryBox(void) /******************************************/ { BASE_SCREEN * Screen = GetScreen();; wxPoint org; int ii, jj; Screen->m_SizeVisu = GetClientSize(); GetViewStart(&org.x, &org.y); GetScrollPixelsPerUnit(&ii, &jj); org.x *= ii; org.y *= jj; Screen->m_StartVisu = org; m_ClipBox.SetOrigin(org); m_ClipBox.SetSize(GetClientSize()); #ifdef WX_ZOOM m_ClipBox.m_Pos.x *= GetZoom(); m_ClipBox.m_Pos.y *= GetZoom(); m_ClipBox.m_Size.x *= GetZoom(); m_ClipBox.m_Size.y *= GetZoom(); #else m_ClipBox.m_Pos.x -= GetScreen()->m_StartVisu.x; m_ClipBox.m_Pos.y -= GetScreen()->m_StartVisu.y; #endif m_ScrollButt_unit = MIN( Screen->m_SizeVisu.x, Screen->m_SizeVisu.y ) / 4; if ( m_ScrollButt_unit < 2 ) m_ScrollButt_unit = 2; Screen->m_ScrollbarPos.x = GetScrollPos(wxHORIZONTAL); Screen->m_ScrollbarPos.y = GetScrollPos(wxVERTICAL); }
void BrushIconBox::EnsureVisible(BrushButton* btn) { int windowSizeX, windowSizeY; GetVirtualSize(&windowSizeX, &windowSizeY); int scrollUnitX; int scrollUnitY; GetScrollPixelsPerUnit(&scrollUnitX, &scrollUnitY); wxRect rect = btn->GetRect(); int y; CalcUnscrolledPosition(0, rect.y, nullptr, &y); int maxScrollPos = windowSizeY / scrollUnitY; int scrollPosY = std::min(maxScrollPos, (y / scrollUnitY)); int startScrollPosY; GetViewStart(nullptr, &startScrollPosY); int clientSizeX, clientSizeY; GetClientSize(&clientSizeX, &clientSizeY); int endScrollPosY = startScrollPosY + clientSizeY / scrollUnitY; if(scrollPosY < startScrollPosY || scrollPosY > endScrollPosY){ //only scroll if the button isnt visible Scroll(-1, scrollPosY); } }
void InstanceCtrl::EnsureRectVisible ( wxRect rect ) { int ppuX, ppuY; GetScrollPixelsPerUnit(& ppuX, & ppuY); if (ppuY == 0) return; int startX, startY; GetViewStart(& startX, & startY); startX = 0; startY = startY * ppuY; int sx, sy; GetVirtualSize(& sx, & sy); sx = 0; if (ppuY != 0) sy = sy / ppuY; wxSize clientSize = GetClientSize(); if ((rect.y + rect.height) > (clientSize.y + startY)) { // Make it scroll so this item is at the bottom // of the window int y = rect.y - (clientSize.y - rect.height - m_spacing) ; SetScrollbars(ppuX, ppuY, sx, sy, 0, (int)(0.5 + y / ppuY)); } else if (rect.y < startY) { // Make it scroll so this item is at the top // of the window int y = rect.y ; SetScrollbars(ppuX, ppuY, sx, sy, 0, (int)(0.5 + y / ppuY)); } }
wxRect wxImageBox::getPaintRect() { wxSize size = GetClientSize(); wxRect paintRect(0, 0, size.GetWidth(), size.GetHeight()); GetViewStart(&paintRect.x, &paintRect.y); int xu,yu; GetScrollPixelsPerUnit(&xu, &yu); paintRect.x *= xu; paintRect.y *= yu; return paintRect; }
void wxLayoutWindow::ScrollToCursor() { //is always needed to make sure we know where the cursor is //if(IsDirty()) //RequestUpdate(m_llist->GetUpdateRect()); ResizeScrollbars(); int x0,y0,x1,y1, dx, dy; // Calculate where the top of the visible area is: GetViewStart(&x0,&y0); GetScrollPixelsPerUnit(&dx, &dy); x0 *= dx; y0 *= dy; WXLO_DEBUG(("ScrollToCursor: GetViewStart is %d/%d", x0, y0)); // Get the size of the visible window: GetClientSize(&x1, &y1); // Make sure that the scrollbars are at a position so that the cursor is // visible if we are editing WXLO_DEBUG(("m_ScrollToCursor = %d", (int) m_ScrollToCursor)); wxPoint cc = m_llist->GetCursorScreenPos(); // the cursor should be completely visible in both directions wxPoint cs(m_llist->GetCursorSize()); int nx = -1, ny = -1; if ( cc.x < x0 || cc.x >= x0 + x1 - cs.x ) { nx = cc.x - x1/2; if ( nx < 0 ) nx = 0; } if ( cc.y < y0 || cc.y >= y0 + y1 - cs.y ) { ny = cc.y - y1/2; if ( ny < 0) ny = 0; } if( nx != -1 || ny != -1 ) { // set new view start Scroll(nx == -1 ? -1 : (nx+dx-1)/dx, ny == -1 ? -1 : (ny+dy-1)/dy); // avoid recursion m_ScrollToCursor = false; RequestUpdate(); } }
// Returns the current scroll position wxPoint wxShapeCanvas::GetCurrentPixelScrollPosition() { int pixelsPerUnitX, pixelsPerUnitY; GetScrollPixelsPerUnit(& pixelsPerUnitX, & pixelsPerUnitY); int posX, posY; GetViewStart(& posX, & posY); wxPoint pt(pixelsPerUnitX * posX, pixelsPerUnitY * posY); return pt; }
void EDA_DRAW_PANEL::OnPan( wxCommandEvent& event ) { int x, y; int ppux, ppuy; int unitsX, unitsY; int maxX, maxY; GetViewStart( &x, &y ); GetScrollPixelsPerUnit( &ppux, &ppuy ); GetVirtualSize( &unitsX, &unitsY ); maxX = unitsX; maxY = unitsY; unitsX /= ppux; unitsY /= ppuy; switch( event.GetId() ) { case ID_PAN_UP: y -= m_scrollIncrementY; break; case ID_PAN_DOWN: y += m_scrollIncrementY; break; case ID_PAN_LEFT: x -= m_scrollIncrementX; break; case ID_PAN_RIGHT: x += m_scrollIncrementX; break; default: wxLogDebug( wxT( "Unknown ID %d in EDA_DRAW_PANEL::OnPan()." ), event.GetId() ); } if( x < 0 ) x = 0; if( y < 0 ) y = 0; if( x > maxX ) x = maxX; if( y > maxY ) y = maxY; Scroll( x/ppux, y/ppuy ); }
void EDA_DRAW_PANEL::MoveCursor( const wxPoint& aPosition ) { if( GetParent()->IsGalCanvasActive() ) return; int x, y, xPpu, yPpu; wxPoint screenPos, drawingPos; wxRect clientRect( wxPoint( 0, 0 ), GetClientSize() ); INSTALL_UNBUFFERED_DC( dc, this ); screenPos.x = dc.LogicalToDeviceX( aPosition.x ); screenPos.y = dc.LogicalToDeviceY( aPosition.y ); // Scroll if the requested mouse position cursor is outside the drawing area. if( !clientRect.Contains( screenPos ) ) { GetViewStart( &x, &y ); GetScrollPixelsPerUnit( &xPpu, &yPpu ); CalcUnscrolledPosition( screenPos.x, screenPos.y, &drawingPos.x, &drawingPos.y ); wxLogTrace( kicadTraceCoords, wxT( "MoveCursor() initial screen position(%d, %d) " ) \ wxT( "rectangle(%d, %d, %d, %d) view(%d, %d)" ), screenPos.x, screenPos.y, clientRect.x, clientRect.y, clientRect.width, clientRect.height, x, y ); if( screenPos.y < clientRect.GetTop() ) y -= m_scrollIncrementY * yPpu; else if( screenPos.y > clientRect.GetBottom() ) y += m_scrollIncrementY * yPpu; else if( clientRect.GetRight() < screenPos.x ) x += m_scrollIncrementX * xPpu; else x -= m_scrollIncrementX * xPpu; Scroll( x, y ); CalcScrolledPosition( drawingPos.x, drawingPos.y, &screenPos.x, &screenPos.y ); wxLogTrace( kicadTraceCoords, wxT( "MoveCursor() scrolled screen position(%d, %d) view(%d, %d)" ), screenPos.x, screenPos.y, x, y ); } WarpPointer( screenPos.x, screenPos.y ); }
wxPoint WinEDA_DrawPanel::CalcAbsolutePosition(const wxPoint & rel_pos) /*********************************************************************/ /* retourne la position absolue en pixels de la position rel_pos, donnée en position relative scrollée (en pixel) */ { wxPoint pos; #ifdef WX_ZOOM CalcUnscrolledPosition( rel_pos.x, rel_pos.y, &pos.x, &pos.y ); #else int ii, jj; GetViewStart(&pos.x, &pos.y); GetScrollPixelsPerUnit(&ii, &jj); pos.x *= ii; pos.y *= jj; pos.x += rel_pos.x; pos.y += rel_pos.y; #endif return pos; }
wxSize MultiDimGridGrid::DoGetBestSize() const { // 100 is the default minimal size of a widget - taken from wx headers. int width = std::max(GetRowLabelSize() + GetColSize(0), 100); int height = std::max(GetColLabelSize() + GetRowSize(0), 100); // The following is from the wx header file for wxScrollWindow: // Round up to a multiple the scroll rate NOTE: this still doesn't get rid // of the scrollbars, is there any magic incantaion for that? int xpu, ypu; GetScrollPixelsPerUnit(&xpu, &ypu); if(xpu) { width += 1 + xpu - (width % xpu); } if(ypu) { height += 1 + ypu - (height % ypu); } return wxSize(width, height); }
// return the size best suited for the current window // (this isn't a virtual size, this is a sensible size for the window) wxSize wxScrolledWindow::DoGetBestSize() const { wxSize best; if ( GetSizer() ) { wxSize b = GetSizer()->GetMinSize(); // Only use the content to set the window size in the direction // where there's no scrolling; otherwise we're going to get a huge // window in the direction in which scrolling is enabled int ppuX, ppuY; GetScrollPixelsPerUnit(& ppuX, & ppuY); wxSize minSize; if ( GetMinSize().IsFullySpecified() ) minSize = GetMinSize(); else minSize = GetSize(); if (ppuX > 0) b.x = minSize.x; if (ppuY > 0) b.y = minSize.y; best = b; } else return wxWindow::DoGetBestSize(); // Add any difference between size and client size wxSize diff = GetSize() - GetClientSize(); best.x += wxMax(0, diff.x); best.y += wxMax(0, diff.y); return best; }
bool InstanceCtrl::GetGroupRect ( int group, wxRect& rect, bool view_relative ) { if (group < GetCount() && group >= 0) { int w,h; GetClientSize(&w, &h); GroupVisual & gv = m_groups[group]; rect.x = 0; rect.y = gv.y_position; rect.width = w; // always fills entire width rect.height = gv.total_height; if (view_relative) { int startX, startY; int xppu, yppu; GetScrollPixelsPerUnit(& xppu, & yppu); GetViewStart(& startX, & startY); rect.x = rect.x - startX * xppu; rect.y = rect.y - startY * yppu; } return true; } }
void EDA_DRAW_PANEL::OnScroll( wxScrollWinEvent& event ) { int id = event.GetEventType(); int x, y; int ppux, ppuy; int csizeX, csizeY; int unitsX, unitsY; GetViewStart( &x, &y ); GetScrollPixelsPerUnit( &ppux, &ppuy ); GetClientSize( &csizeX, &csizeY ); GetVirtualSize( &unitsX, &unitsY ); int tmpX = x; int tmpY = y; csizeX /= ppux; csizeY /= ppuy; unitsX /= ppux; unitsY /= ppuy; int dir = event.GetOrientation(); // wxHORIZONTAL or wxVERTICAL // On windows and on wxWidgets >= 2.9.5 and < 3.1, // there is a bug in mousewheel event which always generates 2 scroll events // (should be the case only for the default mousewheel event) // with id = wxEVT_SCROLLWIN_LINEUP or wxEVT_SCROLLWIN_LINEDOWN // so we skip these events. // Note they are here just in case, because they are not actually used // in Kicad #if wxCHECK_VERSION( 3, 1, 0 ) || !wxCHECK_VERSION( 2, 9, 5 ) || ( !defined (__WINDOWS__) && !defined (__WXMAC__) ) int maxX = unitsX - csizeX; int maxY = unitsY - csizeY; if( id == wxEVT_SCROLLWIN_LINEUP ) { if( dir == wxHORIZONTAL ) { x -= m_scrollIncrementX; if( x < 0 ) x = 0; } else { y -= m_scrollIncrementY; if( y < 0 ) y = 0; } } else if( id == wxEVT_SCROLLWIN_LINEDOWN ) { if( dir == wxHORIZONTAL ) { x += m_scrollIncrementX; if( x > maxX ) x = maxX; } else { y += m_scrollIncrementY; if( y > maxY ) y = maxY; } } else #endif if( id == wxEVT_SCROLLWIN_THUMBTRACK ) { if( dir == wxHORIZONTAL ) x = event.GetPosition(); else y = event.GetPosition(); } else { event.Skip(); return; } wxLogTrace( kicadTraceCoords, wxT( "Setting scroll bars ppuX=%d, ppuY=%d, unitsX=%d, unitsY=%d, posX=%d, posY=%d" ), ppux, ppuy, unitsX, unitsY, x, y ); double scale = GetParent()->GetScreen()->GetScalingFactor(); wxPoint center = GetParent()->GetScrollCenterPosition(); center.x += KiROUND( (double) ( x - tmpX ) / scale ); center.y += KiROUND( (double) ( y - tmpY ) / scale ); GetParent()->SetScrollCenterPosition( center ); Scroll( x, y ); event.Skip(); }
void EDA_DRAW_PANEL::OnPan( wxCommandEvent& event ) { int x, y; int ppux, ppuy; int unitsX, unitsY; int maxX, maxY; int tmpX, tmpY; GetViewStart( &x, &y ); GetScrollPixelsPerUnit( &ppux, &ppuy ); GetVirtualSize( &unitsX, &unitsY ); tmpX = x; tmpY = y; maxX = unitsX; maxY = unitsY; unitsX /= ppux; unitsY /= ppuy; wxLogTrace( kicadTraceCoords, wxT( "Scroll center position before pan: (%d, %d)" ), tmpX, tmpY ); switch( event.GetId() ) { case ID_PAN_UP: y -= m_scrollIncrementY; break; case ID_PAN_DOWN: y += m_scrollIncrementY; break; case ID_PAN_LEFT: x -= m_scrollIncrementX; break; case ID_PAN_RIGHT: x += m_scrollIncrementX; break; default: wxLogDebug( wxT( "Unknown ID %d in EDA_DRAW_PANEL::OnPan()." ), event.GetId() ); } bool updateCenterScrollPos = true; if( x < 0 ) { x = 0; updateCenterScrollPos = false; } if( y < 0 ) { y = 0; updateCenterScrollPos = false; } if( x > maxX ) { x = maxX; updateCenterScrollPos = false; } if( y > maxY ) { y = maxY; updateCenterScrollPos = false; } // Don't update the scroll position beyond the scroll limits. if( updateCenterScrollPos ) { double scale = GetParent()->GetScreen()->GetScalingFactor(); wxPoint center = GetParent()->GetScrollCenterPosition(); center.x += KiROUND( (double) ( x - tmpX ) / scale ); center.y += KiROUND( (double) ( y - tmpY ) / scale ); GetParent()->SetScrollCenterPosition( center ); wxLogTrace( kicadTraceCoords, wxT( "Scroll center position after pan: (%d, %d)" ), center.x, center.y ); } Scroll( x/ppux, y/ppuy ); }
void wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) { wxClientDC dc( this ); PrepareDC( dc ); if ( (eventId != WXLOWIN_MENU_MOUSEMOVE #ifndef __WXMSW__ || m_FocusFollowMode #endif ) && (wxWindow::FindFocus() != this) ) { SetFocus(); } wxPoint findPos; findPos.x = dc.DeviceToLogicalX(event.GetX()); findPos.y = dc.DeviceToLogicalY(event.GetY()); findPos.x -= WXLO_XOFFSET; findPos.y -= WXLO_YOFFSET; if(findPos.x < 0) findPos.x = 0; if(findPos.y < 0) findPos.y = 0; m_ClickPosition = wxPoint(event.GetX(), event.GetY()); // Scroll the window if the mouse is at the end of it: if(m_Selecting && eventId == WXLOWIN_MENU_MOUSEMOVE) { //WXLO_DEBUG(("selecting at : %d/%d", (int) event.GetX(), (int)event.GetY())); int left, top; GetViewStart(&left, &top); wxSize size = GetClientSize(); int xdelta, ydelta; if(event.GetX() < WXLO_SCROLLMARGIN_X) xdelta = -(WXLO_SCROLLMARGIN_X-event.GetX()); else if(event.GetX() > size.x-WXLO_SCROLLMARGIN_X) xdelta = event.GetX()-size.x+WXLO_SCROLLMARGIN_X; else xdelta = 0; if(event.GetY() < WXLO_SCROLLMARGIN_Y) ydelta = -(WXLO_SCROLLMARGIN_Y-event.GetY()); else if(event.GetY() > size.y-WXLO_SCROLLMARGIN_Y) ydelta = event.GetY()-size.y+WXLO_SCROLLMARGIN_Y; else ydelta = 0; //WXLO_DEBUG(("xdelta: %d", (int) xdelta)); if(xdelta != 0 || ydelta != 0) { top += ydelta; if(top < 0) top = 0; left += xdelta; if(left < 0) left = 0; Scroll(left, top); } } wxPoint cursorPos; bool found; wxLayoutObject *obj = m_llist->FindObjectScreen(dc, findPos, &cursorPos, &found); wxLayoutObject::UserData *u = obj ? obj->GetUserData() : NULL; // has the mouse only been moved? switch ( eventId ) { case WXLOWIN_MENU_MOUSEMOVE: { // this variables is used to only erase the message in the status // bar if we had put it there previously - otherwise empting status // bar might be undesirable #if wxUSE_STATUSBAR static bool s_hasPutMessageInStatusBar = false; #endif // wxUSE_STATUSBAR // found is only true if we are really over an object, not just // behind it if(found && u && ! m_Selecting) { if(!m_HandCursor) SetCursor(wxCURSOR_HAND); m_HandCursor = true; #if wxUSE_STATUSBAR if(m_StatusBar && m_StatusFieldLabel != -1) { const wxString &label = u->GetLabel(); if(label.Length()) { m_StatusBar->SetStatusText(label,m_StatusFieldLabel); s_hasPutMessageInStatusBar = true; } } #endif // wxUSE_STATUSBAR } else { if(m_HandCursor) SetCursor(wxCURSOR_IBEAM); m_HandCursor = false; #if wxUSE_STATUSBAR if( m_StatusBar && m_StatusFieldLabel != -1 && s_hasPutMessageInStatusBar ) { m_StatusBar->SetStatusText(wxEmptyString, m_StatusFieldLabel); } #endif // wxUSE_STATUSBAR } } // selecting? if ( event.LeftIsDown() ) { // m_Selecting might not be set if the button got pressed // outside this window, so check for it: if( m_Selecting ) { m_llist->ContinueSelection(cursorPos, m_ClickPosition); RequestUpdate(); // TODO: we don't have to redraw everything! } } if ( u ) { u->DecRef(); u = NULL; } break; case WXLOWIN_MENU_LDOWN: { // always move cursor to mouse click: m_llist->MoveCursorTo(cursorPos); // clicking a mouse removes the selection if ( m_llist->HasSelection() ) { m_llist->DiscardSelection(); m_Selecting = false; RequestUpdate(); // TODO: we don't have to redraw everything! } // Calculate where the top of the visible area is: int x0, y0; GetViewStart(&x0,&y0); int dx, dy; GetScrollPixelsPerUnit(&dx, &dy); x0 *= dx; y0 *= dy; wxPoint offset(-x0+WXLO_XOFFSET, -y0+WXLO_YOFFSET); if(m_CursorVisibility == -1) m_CursorVisibility = 1; #ifdef WXLAYOUT_USE_CARET if ( m_CursorVisibility == 1 ) GetCaret()->Show(); #endif // WXLAYOUT_USE_CARET if(m_CursorVisibility) { // draw a thick cursor for editable windows with focus m_llist->DrawCursor(dc, m_HaveFocus && IsEditable(), offset); } #ifdef __WXGTK__ RequestUpdate(); // RequestUpdate suppresses flicker under GTK #endif // wxGTK // start selection m_llist->StartSelection(wxPoint(-1, -1), m_ClickPosition); m_Selecting = true; } break; case WXLOWIN_MENU_LUP: if ( m_Selecting ) { // end selection at the cursor position corresponding to the // current mouse position, but don´t move cursor there. m_llist->EndSelection(cursorPos,m_ClickPosition); m_Selecting = false; RequestUpdate(); // TODO: we don't have to redraw everything! } break; case WXLOWIN_MENU_MDOWN: Paste(true); break; case WXLOWIN_MENU_DBLCLICK: // select a word under cursor m_llist->MoveCursorTo(cursorPos); m_llist->MoveCursorWord(-1); m_llist->StartSelection(); m_llist->MoveCursorWord(1, false); m_llist->EndSelection(); m_Selecting = false; RequestUpdate(); // TODO: we don't have to redraw everything! break; } // notify about mouse events? if( m_doSendEvents ) { // only do the menu if activated, editable and not on a clickable object if(eventId == WXLOWIN_MENU_RCLICK && IsEditable() && (! obj || u == NULL)) { PopupMenu(m_PopupMenu, m_ClickPosition.x, m_ClickPosition.y); if(u) u->DecRef(); return; } // find the object at this position if(obj) { wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, eventId); commandEvent.SetEventObject( this ); commandEvent.SetClientData((char *)obj); GetEventHandler()->ProcessEvent(commandEvent); } } if( u ) u->DecRef(); }
void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event ) { int localrealbutt = 0, localbutt = 0; BASE_SCREEN* screen = GetScreen(); if( !screen ) return; /* Adjust value to filter mouse displacement before consider the drag * mouse is really a drag command, not just a movement while click */ #define MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND 5 if( event.Leaving() ) m_canStartBlock = -1; if( !IsMouseCaptured() ) // No mouse capture in progress. m_requestAutoPan = false; if( GetParent()->IsActive() ) SetFocus(); else return; if( !event.IsButton() && !event.Moving() && !event.Dragging() ) return; if( event.RightDown() ) { OnRightClick( event ); return; } if( m_ignoreMouseEvents ) return; if( event.LeftIsDown() ) localrealbutt |= GR_M_LEFT_DOWN; if( event.MiddleIsDown() ) localrealbutt |= GR_M_MIDDLE_DOWN; if( event.LeftDown() ) localbutt = GR_M_LEFT_DOWN; if( event.ButtonDClick( 1 ) ) localbutt = GR_M_LEFT_DOWN | GR_M_DCLICK; if( event.MiddleDown() ) localbutt = GR_M_MIDDLE_DOWN; localrealbutt |= localbutt; // compensation default wxGTK INSTALL_UNBUFFERED_DC( DC, this ); DC.SetBackground( *wxBLACK_BRUSH ); // Compute the cursor position in drawing (logical) units. GetParent()->SetMousePosition( event.GetLogicalPosition( DC ) ); int kbstat = 0; if( event.ShiftDown() ) kbstat |= GR_KB_SHIFT; if( event.ControlDown() ) kbstat |= GR_KB_CTRL; if( event.AltDown() ) kbstat |= GR_KB_ALT; // Calling Double Click and Click functions : if( localbutt == (int) ( GR_M_LEFT_DOWN | GR_M_DCLICK ) ) { GetParent()->OnLeftDClick( &DC, GetParent()->RefPos( true ) ); // inhibit a response to the mouse left button release, // because we have a double click, and we do not want a new // OnLeftClick command at end of this Double Click m_ignoreNextLeftButtonRelease = true; } else if( event.LeftUp() ) { // A block command is in progress: a left up is the end of block // or this is the end of a double click, already seen // Note also m_ignoreNextLeftButtonRelease can be set by // the call to OnLeftClick(), so do not change it after calling OnLeftClick bool ignoreEvt = m_ignoreNextLeftButtonRelease; m_ignoreNextLeftButtonRelease = false; if( screen->m_BlockLocate.GetState() == STATE_NO_BLOCK && !ignoreEvt ) GetParent()->OnLeftClick( &DC, GetParent()->RefPos( true ) ); } else if( !event.LeftIsDown() ) { /* be sure there is a response to a left button release command * even when a LeftUp event is not seen. This happens when a * double click opens a dialog box, and the release mouse button * is made when the dialog box is opened. */ m_ignoreNextLeftButtonRelease = false; } if( event.ButtonDown( wxMOUSE_BTN_MIDDLE ) && m_enableMiddleButtonPan ) { if( m_panScrollbarLimits ) { int ppux, ppuy; GetScrollPixelsPerUnit( &ppux, &ppuy ); GetViewStart( &m_PanStartCenter.x, &m_PanStartCenter.y ); m_PanStartCenter.x *= ppux; m_PanStartCenter.y *= ppuy; } else m_PanStartCenter = GetParent()->GetScrollCenterPosition(); m_PanStartEventPosition = event.GetPosition(); INSTALL_UNBUFFERED_DC( dc, this ); CrossHairOff( &dc ); } if( event.ButtonUp( wxMOUSE_BTN_MIDDLE ) && m_enableMiddleButtonPan ) { INSTALL_UNBUFFERED_DC( dc, this ); CrossHairOn( &dc ); } if( event.MiddleIsDown() && m_enableMiddleButtonPan ) { wxPoint currentPosition = event.GetPosition(); if( m_panScrollbarLimits ) { int x, y; int tmpX, tmpY; int ppux, ppuy; int maxX, maxY; int vsizeX, vsizeY; int csizeX, csizeY; GetViewStart( &tmpX, &tmpY ); GetScrollPixelsPerUnit( &ppux, &ppuy ); GetVirtualSize( &vsizeX, &vsizeY ); GetClientSize( &csizeX, &csizeY ); maxX = vsizeX - csizeX; maxY = vsizeY - csizeY; x = m_PanStartCenter.x + m_PanStartEventPosition.x - currentPosition.x; y = m_PanStartCenter.y + m_PanStartEventPosition.y - currentPosition.y; bool shouldMoveCursor = false; if( x < 0 ) { currentPosition.x += x; x = 0; shouldMoveCursor = true; } if( y < 0 ) { currentPosition.y += y; y = 0; shouldMoveCursor = true; } if( x > maxX ) { currentPosition.x += ( x - maxX ); x = maxX; shouldMoveCursor = true; } if( y > maxY ) { currentPosition.y += ( y - maxY ); y = maxY; shouldMoveCursor = true; } if( shouldMoveCursor ) WarpPointer( currentPosition.x, currentPosition.y ); Scroll( x/ppux, y/ppuy ); double scale = GetParent()->GetScreen()->GetScalingFactor(); wxPoint center = GetParent()->GetScrollCenterPosition(); center.x += KiROUND( (double) ( x - tmpX ) / scale ) / ppux; center.y += KiROUND( (double) ( y - tmpY ) / scale ) / ppuy; GetParent()->SetScrollCenterPosition( center ); Refresh(); Update(); } else { double scale = GetParent()->GetScreen()->GetScalingFactor(); int x = m_PanStartCenter.x + KiROUND( (double) ( m_PanStartEventPosition.x - currentPosition.x ) / scale ); int y = m_PanStartCenter.y + KiROUND( (double) ( m_PanStartEventPosition.y - currentPosition.y ) / scale ); GetParent()->RedrawScreen( wxPoint( x, y ), false ); } } if( event.ButtonUp( wxMOUSE_BTN_MIDDLE ) && !m_enableMiddleButtonPan && (screen->m_BlockLocate.GetState() == STATE_NO_BLOCK) ) { // The middle button has been released, with no block command: // We use it for a zoom center at cursor position command wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_POPUP_ZOOM_CENTER ); cmd.SetEventObject( this ); GetEventHandler()->ProcessEvent( cmd ); } // Calling the general function on mouse changes (and pseudo key commands) GetParent()->GeneralControl( &DC, event.GetLogicalPosition( DC ), 0 ); /*******************************/ /* Control of block commands : */ /*******************************/ // Command block can't start if mouse is dragging a new panel static EDA_DRAW_PANEL* lastPanel; if( lastPanel != this ) { m_minDragEventCount = 0; m_canStartBlock = -1; } /* A new command block can start after a release buttons * and if the drag is enough * This is to avoid a false start block when a dialog box is dismissed, * or when changing panels in hierarchy navigation * or when clicking while and moving mouse */ if( !event.LeftIsDown() && !event.MiddleIsDown() ) { m_minDragEventCount = 0; m_canStartBlock = 0; /* Remember the last cursor position when a drag mouse starts * this is the last position ** before ** clicking a button * this is useful to start a block command from the point where the * mouse was clicked first * (a filter creates a delay for the real block command start, and * we must remember this point) */ m_CursorStartPos = GetParent()->GetCrossHairPosition(); } if( m_enableBlockCommands && !(localbutt & GR_M_DCLICK) ) { if( !screen->IsBlockActive() ) { screen->m_BlockLocate.SetOrigin( m_CursorStartPos ); } if( event.LeftDown() || ( !m_enableMiddleButtonPan && event.MiddleDown() ) ) { if( screen->m_BlockLocate.GetState() == STATE_BLOCK_MOVE ) { m_requestAutoPan = false; GetParent()->HandleBlockPlace( &DC ); m_ignoreNextLeftButtonRelease = true; } } else if( ( m_canStartBlock >= 0 ) && ( event.LeftIsDown() || ( !m_enableMiddleButtonPan && event.MiddleIsDown() ) ) && !IsMouseCaptured() ) { // Mouse is dragging: if no block in progress, start a block command. if( screen->m_BlockLocate.GetState() == STATE_NO_BLOCK ) { // Start a block command int cmd_type = kbstat; if( !m_enableMiddleButtonPan && event.MiddleIsDown() ) cmd_type |= MOUSE_MIDDLE; // A block command is started if the drag is enough. A small // drag is ignored (it is certainly a little mouse move when // clicking) not really a drag mouse if( m_minDragEventCount < MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND ) m_minDragEventCount++; else { if( !GetParent()->HandleBlockBegin( &DC, cmd_type, m_CursorStartPos ) ) { // should not occur: error GetParent()->DisplayToolMsg( wxT( "EDA_DRAW_PANEL::OnMouseEvent() Block Error" ) ); } else { m_requestAutoPan = true; SetCursor( wxCURSOR_SIZING ); } } } } if( event.ButtonUp( wxMOUSE_BTN_LEFT ) || ( !m_enableMiddleButtonPan && event.ButtonUp( wxMOUSE_BTN_MIDDLE ) ) ) { /* Release the mouse button: end of block. * The command can finish (DELETE) or have a next command (MOVE, * COPY). However the block command is canceled if the block * size is small because a block command filtering is already * made, this case happens, but only when the on grid cursor has * not moved. */ #define BLOCK_MINSIZE_LIMIT 1 bool BlockIsSmall = ( std::abs( screen->m_BlockLocate.GetWidth() ) < BLOCK_MINSIZE_LIMIT ) && ( std::abs( screen->m_BlockLocate.GetHeight() ) < BLOCK_MINSIZE_LIMIT ); if( (screen->m_BlockLocate.GetState() != STATE_NO_BLOCK) && BlockIsSmall ) { if( m_endMouseCaptureCallback ) { m_endMouseCaptureCallback( this, &DC ); m_requestAutoPan = false; } SetCursor( (wxStockCursor) m_currentCursor ); } else if( screen->m_BlockLocate.GetState() == STATE_BLOCK_END ) { m_requestAutoPan = false; GetParent()->HandleBlockEnd( &DC ); SetCursor( (wxStockCursor) m_currentCursor ); if( screen->m_BlockLocate.GetState() == STATE_BLOCK_MOVE ) { m_requestAutoPan = true; SetCursor( wxCURSOR_HAND ); } } } } // End of block command on a double click // To avoid an unwanted block move command if the mouse is moved while double clicking if( localbutt == (int) ( GR_M_LEFT_DOWN | GR_M_DCLICK ) ) { if( !screen->IsBlockActive() && IsMouseCaptured() ) { m_endMouseCaptureCallback( this, &DC ); } } #if 0 wxString msg_debug; msg_debug.Printf( " block state %d, cmd %d", screen->m_BlockLocate.GetState(), screen->m_BlockLocate.GetCommand() ); GetParent()->PrintMsg( msg_debug ); #endif lastPanel = this; }
void WinEDA_DrawPanel::DrawBackGround(wxDC * DC) /***********************************************/ /* Trace les axes X et Y et la grille La grille n'est affichee que si elle peut etre facilement visible La grille passe toujours par le centre de l'ecran */ { int Color = BLUE; BASE_SCREEN * screen = GetScreen(); int ii,jj ,xg , yg , color; wxSize pas_grille_affichee; bool drawgrid = FALSE; int zoom = GetZoom(); wxSize size; wxPoint org; double pasx, pasy; color = screen->m_GridColor; GRSetDrawMode(DC, GR_COPY); /* le pas d'affichage doit etre assez grand pour avoir une grille visible */ drawgrid = m_Parent->m_Draw_Grid; pas_grille_affichee = screen->GetGrid(); ii = pas_grille_affichee.x / zoom; if (ii < 5 ) { pas_grille_affichee.x *= 2 ; ii *= 2; } if( ii < 5 ) drawgrid = FALSE; // grille trop petite ii = pas_grille_affichee.y / zoom; if (ii < 5 ) { pas_grille_affichee.y *= 2 ; ii *= 2; } if( ii < 5 ) drawgrid = FALSE; // grille trop petite GetViewStart(&org.x, &org.y); GetScrollPixelsPerUnit(&ii, &jj); org.x *= ii; org.y *= jj; screen->m_StartVisu = org; org.x *= zoom; org.y *= zoom; org.x += screen->m_DrawOrg.x; org.y += screen->m_DrawOrg.y; size = GetClientSize(); size.x *= zoom; size.y *= zoom; pasx = screen->m_UserGrid.x * m_Parent->m_InternalUnits; pasy = screen->m_UserGrid.y * m_Parent->m_InternalUnits; if ( screen->m_UserGridUnit != INCHES ) { pasx /= 25.4; pasy /= 25.4; } if( drawgrid) { m_Parent->PutOnGrid(&org) ; GRSetColorPen(DC, color ); for ( ii = 0 ; ; ii++ ) { xg = screen->m_UserGridIsON ? (int)( (ii * pasx) + 0.5) :ii * pas_grille_affichee.x; int xpos = org.x + xg; for ( jj = 0 ; ; jj++ ) { yg = screen->m_UserGridIsON ? (int)( (jj * pasy) + 0.5) : jj * pas_grille_affichee.y; GRPutPixel(&m_ClipBox, DC, xpos, org.y + yg, color); if ( yg > size.y ) break; } if ( xg > size.x ) break; } } /* trace des axes principaux */ if ( m_Parent->m_Draw_Axes ) { /* Trace de l'axe vertical */ GRDashedLine(&m_ClipBox, DC, 0, -screen->ReturnPageSize().y, 0, screen->ReturnPageSize().y, Color ); /* Trace de l'axe horizontal */ GRDashedLine(&m_ClipBox, DC, -screen->ReturnPageSize().x, 0, screen->ReturnPageSize().x, 0, Color ); } /* trace des axes auxiliaires */ if ( m_Parent->m_Draw_Auxiliary_Axe) { m_Draw_Auxiliary_Axe(DC, FALSE); } }
/// Find the item under the given point void InstanceCtrl::HitTest( const wxPoint& pt, VisualCoord& n ) { wxSize clientSize = GetClientSize(); int startX, startY; int ppuX, ppuY; n.makeVoid(); GetViewStart(& startX, & startY); GetScrollPixelsPerUnit(& ppuX, & ppuY); int perRow = GetItemsPerRow(); int colPos = (int)(pt.x / (m_itemWidth + m_spacing)); int rowPos = 0; int actualY = pt.y + startY * ppuY; GroupVisual * found = nullptr; int grpIdx = 0; for(; grpIdx < m_groups.size(); grpIdx++) { GroupVisual & gv = m_groups[grpIdx]; if (actualY >= gv.y_position && actualY <= gv.y_position + gv.total_height) { found = &gv; n.makeGroup(grpIdx); if (!gv.no_header && actualY <= gv.y_position + gv.header_height) { // it's a header if(pt.x >= 5 && pt.x <= 15) { // it's the ticker thing n.makeHeaderTicker(grpIdx); } else { // it's the header in general n.makeHeader(grpIdx); } return; } break; } } // it's not even a group if(!found) return; while (rowPos < found->row_ys.size() && found->y_position + found->row_ys[rowPos] < actualY) rowPos++; rowPos--; int itemN = (rowPos * perRow + colPos); if (itemN >= found->items.size() || itemN < 0) return; wxRect rect; VisualCoord coord(grpIdx, itemN); GetItemRect(coord, rect); if (rect.Contains(pt)) { n = coord; } }