Main Page | Namespace List | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

exsplitter.cpp

Go to the documentation of this file.
00001 
00002 // Name:        wxExSplitter.cpp
00003 // Purpose:     wxExSplitter implementation.
00004 // Author:      Mark McCormack
00005 // Modified by:
00006 // Created:     23/02/04
00007 // RCS-ID:      $Id: exsplitter.cpp,v 1.6 2005/05/12 14:04:48 frm Exp $
00008 // Copyright:   (c) 2004 Mark McCormack
00009 // Licence:     wxWindows license
00011 
00012 #include <wx/exsplitter.h>
00013 #include <wx/gdi.h>
00014 #include <wx/dockhost.h>
00015 
00016 #include <wx/dcscreen.h>
00017 
00018 // ----------------------------------------------------------------------------
00019 // wxExSplitter implementation
00020 // ----------------------------------------------------------------------------
00021 
00022 IMPLEMENT_CLASS( wxExSplitter, wxWindow )
00023 DEFINE_EVENT_TYPE( wxEVT_SPLITTER_MOVED )
00024 
00025 BEGIN_EVENT_TABLE( wxExSplitter, wxWindow )
00026     EVT_LEFT_DOWN( wxExSplitter::OnLeftDown )
00027     EVT_MOTION( wxExSplitter::OnMouseMove )
00028     EVT_LEFT_UP( wxExSplitter::OnLeftUp )
00029     EVT_ERASE_BACKGROUND( wxExSplitter::OnErase )
00030     EVT_PAINT( wxExSplitter::OnPaint )
00031 END_EVENT_TABLE()
00032 
00033 void wxExSplitter::Init() {
00034     memset(&pWindow_, 0, sizeof(pWindow_));
00035     pOwner_ = NULL;
00036     bounded_ = false;
00037     dragging_ = false;
00038     minSize_ = wxMINIMUM_WINDOW_SIZE;
00039     flags_ = 0x0000;
00040     startPosition_.x = startPosition_.y = 0;
00041 }
00042 
00043 bool wxExSplitter::Create( wxWindow * parent, wxOrientation orientation, wxWindow * win1, wxWindow * win2, unsigned int flags ) {
00044     wxASSERT(parent);
00045     bool r = wxWindow::Create( parent, -1, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE );
00046 
00047     // assign
00048     pOwner_ = parent;
00049     pWindow_[0] = win1;
00050     pWindow_[1] = win2;
00051     orientation_ = orientation;
00052     flags_ = flags;
00053 
00054     // set the type of cursor we need
00055     if( orientation_ == wxHORIZONTAL ) {
00056         SetCursor( g_gdi.GetHSplitCursor() );
00057     }
00058     else {
00059         SetCursor( g_gdi.GetVSplitCursor() );
00060     }
00061 
00062     return r;
00063 }
00064 
00065 void wxExSplitter::SetWindows( wxWindow * pWin1, wxWindow * pWin2 ) {
00066     // set windows
00067     pWindow_[0] = pWin1;
00068     pWindow_[1] = pWin2;
00069 }
00070 
00071 void wxExSplitter::SetFlags( unsigned int flags ) {
00072     flags_ = flags;
00073 }
00074 
00075 void wxExSplitter::OnLeftDown( wxMouseEvent& event ) {
00076     // take origin
00077     startPosition_ = ClientToScreen( event.GetPosition() );
00078     dragging_ = true;
00079     
00080     // take snapshots
00081     startRect_[0] = pWindow_[0] ? pWindow_[0]->GetRect() : wxRect();
00082     startRect_[1] = pWindow_[1] ? pWindow_[1]->GetRect() : wxRect();
00083     startRectUs_ = GetRect();
00084     endRectUs_ = startRectUs_;
00085     
00086     // check boundaries
00087     SetBoundaries();
00088 
00089     // draw start position
00090  lastDrawnRect_ = wxRect();
00091 #ifndef __WXGTK__
00092  // XXX: work-around for GTK, due to GTK repainting over our initial screen XOR rectangle, it is best for
00093  // now to not draw the initial XOR rectangle under this platform
00094     draw( startRectUs_ );
00095 #endif 
00096     
00097     // we want all further mouse events
00098     CaptureMouse();
00099 }
00100 
00101 void wxExSplitter::OnMouseMove( wxMouseEvent& event ) {
00102     if( dragging_ ) {
00103         wxPoint pos = ClientToScreen( event.GetPosition() );
00104 
00105         if (bounded_) {
00106             // check for boundary crossing
00107             if ((pos.x < boundary[0].x) ||
00108                 (pos.x > boundary[1].x) ||
00109                 (pos.y < boundary[0].y) ||
00110                 (pos.y > boundary[1].y)) {
00111                 return;
00112             }
00113         }
00114 
00115         wxRect r0 = startRect_[0], r1 = startRect_[1], r = startRectUs_;
00116         if( orientation_ == wxHORIZONTAL ) {
00117             // resize in the horizontal
00118             int dx = pos.x - startPosition_.x;
00119             if( pWindow_[0] && (r0.width + dx) < minSize_ ) dx = minSize_ - r0.width;
00120             if( pWindow_[1] && (r1.width - dx) < minSize_ ) dx = r1.width - minSize_;
00121 
00122             r0.width += dx;
00123             r1.width -= dx;
00124             r1.x += dx;
00125             r.x += dx;
00126         }
00127         else {
00128             // resize in the vertical
00129             int dy = pos.y - startPosition_.y;
00130             if( pWindow_[0] && (r0.height + dy) < minSize_ ) dy = minSize_ - r0.height;
00131             if( pWindow_[1] && (r1.height - dy) < minSize_ ) dy = r1.height - minSize_;
00132 
00133             r0.height += dy;
00134             r1.height -= dy;
00135             r1.y += dy;
00136             r.y += dy;
00137         }
00138         
00139         // perform the actual re-sizes
00140         if( flags_ & wxESF_LIVE_UPDATE ) {
00141             // update now
00142             if( pWindow_[0] ) pWindow_[0]->SetSize( r0 );
00143             if( pWindow_[1] ) pWindow_[1]->SetSize( r1 );
00144             if( !pWindow_[0] ) {
00145                 // don't alter x/y for right/bottom single edge cases
00146                 r.x = startRectUs_.x;
00147                 r.y = startRectUs_.y;
00148             }
00149             SetSize( r );
00150 
00151             // generate size change event
00152             wxCommandEvent e( wxEVT_SPLITTER_MOVED, GetId() );
00153             e.SetEventObject( this );
00154             GetEventHandler()->ProcessEvent( e );
00155         }
00156         else {
00157             // draw now...
00158    if( lastDrawnRect_.GetWidth() && lastDrawnRect_.GetHeight() ) {
00159              draw( lastDrawnRect_ );
00160    }
00161             draw( r );
00162             
00163             // ...update later
00164             endRect_[0] = r0;
00165             endRect_[1] = r1;
00166             endRectUs_ = r;
00167             if( !pWindow_[0] ) {
00168                 // don't alter x/y for right/bottom single edge cases
00169                 endRectUs_.x = startRectUs_.x;
00170                 endRectUs_.y = startRectUs_.y;
00171             }
00172         }
00173     }
00174 }
00175 
00176 void wxExSplitter::OnErase( wxEraseEvent& WXUNUSED(event) ) {
00177     // skip erase
00178 }
00179 
00180 void wxExSplitter::OnPaint( wxPaintEvent& WXUNUSED(event) ) {
00181     wxPaintDC dc(this);
00182  
00183     wxRect cr = GetClientRect();
00184  
00185     // draw physical splitter image
00186  if( flags_ & wxESF_DRAW_GRIPPER ) {
00187   g_gdi.DrawSplitter( dc, cr, orientation_ );
00188  }
00189     else {
00190   g_gdi.DrawBackground( dc, cr );
00191     }
00192 }
00193 
00194 void wxExSplitter::OnLeftUp( wxMouseEvent& WXUNUSED(event) ) {
00195     if( !dragging_ ) return;
00196 
00197     // release mouse
00198     ReleaseMouse();
00199     dragging_ = false;
00200 
00201     // need to update here?
00202     if( !(flags_ & wxESF_LIVE_UPDATE) ) {
00203         // erase end position
00204         draw( lastDrawnRect_ );
00205 
00206         if( endRectUs_.GetWidth() || endRectUs_.GetHeight() ) {
00207             // update associated windows
00208             for( int i=0; i<wxSPLITTER_WINDOWS; i++ ) {
00209                 // make sure window pointer valid
00210                 if( pWindow_[i] ) {
00211                     // make sure new size rectangle valid
00212                     if( endRect_[i].GetWidth() || endRect_[i].GetHeight() ) {
00213                         pWindow_[i]->SetSize( endRect_[i] );
00214                     }
00215                 }
00216             }
00217             SetSize( endRectUs_ );        
00218         }
00219     }
00220 
00221     // generate size change event
00222     wxCommandEvent e(wxEVT_SPLITTER_MOVED, GetId());
00223     e.SetEventObject(this);
00224     GetEventHandler()->ProcessEvent(e);
00225 }
00226 
00227 void wxExSplitter::draw( wxRect r ) {
00228     if( flags_ & wxESF_LIVE_UPDATE ) return;
00229     
00230     // draw our position onto the screen [XOR]
00231     wxScreenDC dc;
00232 
00233     wxRect screenRect = r;
00234     screenRect.SetPosition( pOwner_->ClientToScreen( screenRect.GetPosition() ) );
00235     g_gdi.DrawPattern( dc, screenRect );
00236     lastDrawnRect_ = r;
00237 }
00238 
00239 void wxExSplitter::SetBoundaries() {
00240     bounded_ = false;
00241 
00242     if ((pWindow_[0] && pWindow_[1]) || (!pWindow_[0] && !pWindow_[1])) {
00243         return;
00244     }
00245 
00246     wxDockHost* dh = wxDynamicCast(pOwner_, wxDockHost);
00247 
00248     if (!dh || (dh -> GetSizingSplitter() != this)) {
00249         return;
00250     }
00251 
00252     bounded_ = true;
00253 
00254     wxWindow* parent = dh -> GetParent();
00255     wxLayoutManager* pLayoutManager = dh -> GetLayoutManager();
00256     wxSize clientSize = parent -> GetClientSize();
00257 
00258     if (pLayoutManager) {
00259         wxRect dockArea = pLayoutManager->GetDockArea();
00260         boundary[0] = dockArea.GetPosition();
00261         clientSize = dockArea.GetSize();
00262     }
00263     else {
00264         boundary[0] = wxPoint(0, 0);
00265         clientSize = parent->GetClientSize();
00266     }
00267     boundary[0] = parent->ClientToScreen(boundary[0]);
00268 
00269     boundary[0].x += wxSPLITTER_SIZE;
00270     boundary[0].y += wxSPLITTER_SIZE;
00271 
00272     boundary[1] = boundary[0];
00273 
00274     boundary[1].x += (clientSize.GetWidth() - (wxSPLITTER_SIZE * 2));
00275     boundary[1].y += (clientSize.GetHeight() - (wxSPLITTER_SIZE * 2));
00276 
00277     if (!pLayoutManager) {
00278         return;
00279     }
00280 
00281     // search other dockhosts with this orientation
00282     wxDirection ldir = wxALL;
00283 
00284     switch (dh -> GetDirection()) {
00285     case wxLEFT   :
00286         ldir = wxRIGHT;  break;
00287     case wxRIGHT  :
00288         ldir = wxLEFT;   break;
00289     case wxTOP    :
00290         ldir = wxBOTTOM; break;
00291     case wxBOTTOM :
00292         ldir = wxTOP;    break;
00293     default       :
00294         ldir = wxALL;    break;
00295     }
00296 
00297     if (ldir == wxALL) {
00298         return;
00299     }
00300 
00301     wxDockHost* dockhost = pLayoutManager -> GetDockHost(ldir);
00302     if (dockhost && !dockhost -> IsEmpty()) {
00303         wxRect hr = dockhost -> GetScreenArea();
00304 
00305         switch (ldir) {
00306         case wxLEFT   :
00307             boundary[0].x = hr.GetRight() + wxSPLITTER_SIZE; break;
00308         case wxRIGHT  :
00309             boundary[1].x = hr.GetLeft() - wxSPLITTER_SIZE; break;
00310         case wxTOP    :
00311             boundary[0].y = hr.GetBottom() + wxSPLITTER_SIZE; break;
00312         case wxBOTTOM :
00313             boundary[1].y = hr.GetTop() - wxSPLITTER_SIZE; break;
00314         case wxALL    :
00315             wxASSERT(false); break;
00316         }
00317     }
00318 }

Generated on Sat May 14 14:54:39 2005 for wxDockIt by  doxygen 1.4.2