MatOCAD Logo

Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

resize.cpp

Go to the documentation of this file.
00001 
00012 #include "../../include/wxIFM/resize.h"
00013 
00014 #include <wx/msgdlg.h>
00015 #include <wx/settings.h>
00016 
00017 DEFINE_IFM_DATA_KEY(IFM_RESIZE_DATA_KEY)
00018 
00019 DEFINE_EVENT_TYPE(wxEVT_IFM_BEGINRESIZE)
00020 DEFINE_EVENT_TYPE(wxEVT_IFM_ENDRESIZE)
00021 DEFINE_EVENT_TYPE(wxEVT_IFM_RESIZE)
00022 DEFINE_EVENT_TYPE(wxEVT_IFM_RESIZESASHDBLCLICK)
00023 DEFINE_EVENT_TYPE(wxEVT_IFM_GETRESIZESASHRECT)
00024 DEFINE_EVENT_TYPE(wxEVT_IFM_UPDATERESIZESASHES)
00025 
00026 #if IFM_USE_WX_RTTI
00027 IMPLEMENT_DYNAMIC_CLASS(wxIFMResizeData, wxIFMChildDataBase);
00028 IMPLEMENT_DYNAMIC_CLASS(wxIFMDefaultResizePlugin, wxIFMExtensionPluginBase);
00029 #endif
00030 
00031 BEGIN_EVENT_TABLE(wxIFMDefaultResizePlugin, wxEvtHandler)
00032     EVT_IFM_NEWCOMPONENT    (wxIFMDefaultResizePlugin::OnCreateComponent)
00033     EVT_IFM_DOCK            (wxIFMDefaultResizePlugin::OnDock)
00034     EVT_IFM_UNDOCK          (wxIFMDefaultResizePlugin::OnUndock)
00035     EVT_IFM_CONVERTRECT     (wxIFMDefaultResizePlugin::OnConvertRect)
00036     EVT_IFM_SHOWCHILD       (wxIFMDefaultResizePlugin::OnShowChild)
00037     EVT_IFM_HIDECHILD       (wxIFMDefaultResizePlugin::OnShowChild)
00038     EVT_IFM_PAINTDECOR      (wxIFMDefaultResizePlugin::OnPaintDecor)
00039     EVT_IFM_GETRESIZESASHRECT(wxIFMDefaultResizePlugin::OnGetRect)
00040     EVT_IFM_SETRECT         (wxIFMDefaultResizePlugin::OnSetRect)
00041     EVT_IFM_SETCURSOR       (wxIFMDefaultResizePlugin::OnSetCursor)
00042 
00043 #if IFM_CANFLOAT
00044     EVT_IFM_FLOAT           (wxIFMDefaultResizePlugin::OnFloat)
00045 #endif
00046 
00047     EVT_IFM_LEFTDOWN        (wxIFMDefaultResizePlugin::OnLeftDown)
00048     EVT_IFM_LEFTUP          (wxIFMDefaultResizePlugin::OnLeftUp)
00049     EVT_IFM_MOTION          (wxIFMDefaultResizePlugin::OnMouseMove)
00050     EVT_IFM_KEYDOWN         (wxIFMDefaultResizePlugin::OnKeyDown)
00051 
00052     EVT_IFM_ADDTOPCONTAINER (wxIFMDefaultResizePlugin::OnAddTopContainer)
00053     EVT_IFM_RESIZE_BEGIN    (wxIFMDefaultResizePlugin::OnResizeBegin)
00054     EVT_IFM_RESIZE_END      (wxIFMDefaultResizePlugin::OnResizeEnd)
00055     EVT_IFM_RESIZE_RESIZING (wxIFMDefaultResizePlugin::OnResizing)
00056     EVT_IFM_RESIZE_UPDATE_SASHES (wxIFMDefaultResizePlugin::OnUpdateResizeSashes)
00057 END_EVENT_TABLE()
00058 
00059 wxIFMDefaultResizePlugin::wxIFMDefaultResizePlugin()
00060     : wxIFMExtensionPluginBase(),
00061     m_ip(NULL),
00062     m_resizing(false),
00063     m_realtime(false),
00064     m_oldPos(wxPoint(-1,-1))
00065 { }
00066 
00067 bool wxIFMDefaultResizePlugin::Initialize(wxIFMInterfacePluginBase *plugin)
00068 {
00069     wxIFMExtensionPluginBase::Initialize(plugin);
00070 
00071 #if IFM_USE_WX_RTTI
00072     m_ip = wxDynamicCast(plugin, wxIFMDefaultInterfacePlugin);
00073 #else
00074     m_ip = dynamic_cast<wxIFMDefaultInterfacePlugin*>(plugin);
00075 #endif
00076 
00077     if( !m_ip )
00078     {
00079         wxMessageBox(wxT("wxIFMDefaultResizePlugin only extends wxIFMDefaultInterfacePlugin"), wxT("Error"),
00080             wxICON_ERROR | wxOK);
00081         return false;
00082     }
00083 
00084     return true;
00085 }
00086 
00087 void wxIFMDefaultResizePlugin::OnCreateComponent(wxIFMNewComponentEvent &event)
00088 {
00089     // let the component be created first
00090     GetNextHandler()->ProcessEvent(event);
00091 
00092     // add resize data to components
00093     wxIFMResizeData *data = new wxIFMResizeData;
00094     wxIFMComponent *component = event.GetComponent();
00095 
00096     wxASSERT_MSG(component, wxT("NULL component?"));
00097     if( !component )
00098         return;
00099 
00100     component->AddExtensionData(data);
00101 }
00102 
00103 void wxIFMDefaultResizePlugin::OnDock(wxIFMDockEvent &event)
00104 {
00105     // let the component be docked first
00106     GetNextHandler()->ProcessEvent(event);
00107 
00108     wxIFMComponent *dest = event.GetDestination();
00109     wxASSERT_MSG(dest, wxT("NULL destination?"));
00110     if( !dest )
00111         return;
00112 
00113     wxIFMUpdateResizeSashEvent evt(dest);
00114     GetIP()->ProcessPluginEvent(evt);
00115 }
00116 
00117 void wxIFMDefaultResizePlugin::OnUndock(wxIFMUndockEvent &event)
00118 {
00119     if( event.GetParentType() != IFM_COMPONENT_CONTAINER )
00120     {
00121         event.Skip();
00122         return;
00123     }
00124 
00125     wxIFMComponent *component = event.GetComponent();
00126     wxASSERT_MSG(component, wxT("NULL component?"));
00127     if( !component )
00128         return;
00129 
00130     // I need to determine before hand how many children will remain after the undock command is processed
00131     // If no children are left the container _may_ be destroyed and the parent pointer will point to a freed
00132     // object
00133     bool update = false;
00134     if( event.GetParent()->m_children.GetCount() > 1 )
00135         update = true;
00136 
00137     GetNextHandler()->ProcessEvent(event);
00138 
00139     if( update )
00140     {
00141         wxIFMUpdateResizeSashEvent evt(event.GetParent());
00142         GetIP()->ProcessPluginEvent(evt);
00143     }
00144 }
00145 
00146 void wxIFMDefaultResizePlugin::OnAddTopContainer(wxIFMAddTopContainerEvent &event)
00147 {
00148     GetNextHandler()->ProcessEvent(event);
00149 
00150     wxIFMComponent *component = event.GetComponent();
00151     wxASSERT_MSG(component, wxT("NULL component?"));
00152     if( !component )
00153         return;
00154 
00155     wxIFMUpdateResizeSashEvent evt(component);
00156     GetIP()->ProcessPluginEvent(evt);
00157 }
00158 
00159 void wxIFMDefaultResizePlugin::OnShowChild(wxIFMShowChildEvent &event)
00160 {
00161     // let the child be shown or hidden first
00162     GetNextHandler()->ProcessEvent(event);
00163 
00164     wxIFMComponent *component = event.GetComponent();
00165     wxASSERT_MSG(component, wxT("NULL component?"));
00166     if( !component )
00167         return;
00168 
00169     wxIFMComponent *parent = component->m_parent;
00170 
00171     if( parent ) // just to be sure
00172     {
00173         wxIFMUpdateResizeSashEvent evt(parent);
00174         GetIP()->ProcessPluginEvent(evt);
00175     }
00176 }
00177 
00178 #if IFM_CANFLOAT
00179 void wxIFMDefaultResizePlugin::OnFloat(wxIFMFloatEvent &event)
00180 {
00181     GetNextHandler()->ProcessEvent(event);
00182 
00183     wxIFMComponent *component = event.GetComponent();
00184 
00185     wxASSERT_MSG(component, wxT("NULL component?"));
00186     if( !component )
00187         return;
00188 
00189     wxIFMResizeData *data = IFM_GET_EXTENSION_DATA(component, wxIFMResizeData);
00190 
00191     wxASSERT_MSG(data, wxT("no resize data?"));
00192     if( !data )
00193         return;
00194 
00195     // don't display resize sashes on the root component of a floating window
00196     if( !component->m_docked )
00197     {
00198         data->m_display = false;
00199     }
00200 
00201     wxIFMUpdateResizeSashEvent evt(component);
00202     GetIP()->ProcessPluginEvent(evt);
00203 }
00204 #endif
00205 
00206 void wxIFMDefaultResizePlugin::OnUpdateResizeSashes(wxIFMUpdateResizeSashEvent &event)
00207 {
00208     wxIFMComponent *component = event.GetComponent();
00209 
00210     wxASSERT_MSG(component, wxT("NULL component?"));
00211     if( !component )
00212         return;
00213 
00214     if( component->GetType() == IFM_COMPONENT_CONTAINER )
00215         UpdateContainerResizeSashes(component);
00216     else
00217         UpdateResizeSashes(component);
00218 }
00219 
00220 void wxIFMDefaultResizePlugin::UpdateContainerResizeSashes(wxIFMComponent *container)
00221 {
00222     // give the container a resize sash
00223     wxIFMContainerData *contdata = IFM_GET_EXTENSION_DATA(container, wxIFMContainerData);
00224     wxIFMResizeData *contresizedata = IFM_GET_EXTENSION_DATA(container, wxIFMResizeData);
00225 
00226     // should we display a sash?
00227 #if IFM_CANFLOAT
00228     wxIFMFloatingData *floating_data = IFM_GET_EXTENSION_DATA(container, wxIFMFloatingData);
00229 #endif
00230 
00231     if( HasResizeableChildren(container)
00232 #if IFM_CANFLOAT
00233         && !(floating_data->m_floating && !container->m_docked)
00234 #endif
00235       )
00236     {
00237         contresizedata->m_display = true;
00238     }
00239     else
00240         contresizedata->m_display = false;
00241 
00242     // always give the sash a side
00243     switch(contdata->m_orientation)
00244     {
00245         case IFM_ORIENTATION_LEFT:
00246             contresizedata->m_side = IFM_ORIENTATION_RIGHT;
00247             break;
00248         case IFM_ORIENTATION_TOP:
00249             contresizedata->m_side = IFM_ORIENTATION_BOTTOM;
00250             break;
00251         case IFM_ORIENTATION_RIGHT:
00252             contresizedata->m_side = IFM_ORIENTATION_LEFT;
00253             break;
00254         case IFM_ORIENTATION_BOTTOM:
00255             contresizedata->m_side = IFM_ORIENTATION_TOP;
00256             break;
00257         //case IFM_ORIENTATION_DOCKED:
00258         default:
00259             // decide based on scale direction
00260             if( container->m_alignment == IFM_ALIGN_HORIZONTAL )
00261                 contresizedata->m_side = IFM_ORIENTATION_BOTTOM;
00262             else if( container->m_alignment == IFM_ALIGN_VERTICAL )
00263                 contresizedata->m_side = IFM_ORIENTATION_RIGHT;
00264     }
00265 
00266     // update children
00267     UpdateResizeSashes(container);
00268 }
00269 
00270 void wxIFMDefaultResizePlugin::UpdateResizeSashes(wxIFMComponent *component)
00271 {
00272     wxIFMResizeData *resizedata;
00273 
00275     // this would mean that the first visible child doesn't have a sash
00276     // as compared to the last visible child having no sash with right / bottom
00277     int next = 0, current = wxIFMComponent::GetNextVisibleComponent(component->m_children, 0);
00278 
00279     // if there are no visible children, do not display a resize sash on the container
00280     // never display a resize sash on a docked container
00281     resizedata = IFM_GET_EXTENSION_DATA(component, wxIFMResizeData);
00282 
00283     #if IFM_CANFLOAT
00284     wxIFMFloatingData *floating_data = IFM_GET_EXTENSION_DATA(component, wxIFMFloatingData);
00285 #endif
00286 
00287     if( !HasResizeableChildren(component)
00288 #if IFM_CANFLOAT
00289         || (floating_data->m_floating && !component->m_docked)
00290 #endif
00291       )
00292     {
00293         resizedata->m_display = false;
00294     }
00295     else
00296         resizedata->m_display = true;
00297 
00298     // don't display the sash if there are no children
00299     /*
00300     if( current == -1 )
00301         resizedata->m_display = false;
00302     else
00303         resizedata->m_display = true;
00304         */
00305 
00306     // determine resize sash side
00307     int side = 0;
00308     if( component->m_alignment == IFM_ALIGN_VERTICAL )
00309         side = IFM_ORIENTATION_BOTTOM;
00310     else if( component->m_alignment == IFM_ALIGN_HORIZONTAL )
00311         side = IFM_ORIENTATION_RIGHT;
00312 
00313     // iterate over visible children
00314     while( current >= 0 )
00315     {
00316         next = wxIFMComponent::GetNextVisibleComponent(component->m_children, current + 1);
00317 
00318         resizedata = IFM_GET_EXTENSION_DATA(component->m_children[current], wxIFMResizeData);
00319         resizedata->m_side = side;
00320 
00321         if( next != -1 && !component->m_children[current]->m_fixed )
00322             resizedata->m_display = true;
00323         else
00324             resizedata->m_display = false;
00325 
00326         current = next;
00327     }
00328 
00329     // update the parent too
00330     if( component->m_parent )
00331     {
00332         wxIFMUpdateResizeSashEvent evt(component->m_parent);
00333         GetIP()->ProcessPluginEvent(evt);
00334     }
00335 }
00336 
00337 void wxIFMDefaultResizePlugin::OnConvertRect(wxIFMConvertRectEvent &event)
00338 {
00339     wxIFMComponent *component = event.GetComponent();
00340     wxIFMResizeData *data = IFM_GET_EXTENSION_DATA(component, wxIFMResizeData);
00341 
00342     // don't do anything if sash is hidden or if the component is hidden
00343     if( !data->m_display || component->m_hidden)
00344     {
00345         event.Skip();
00346         return;
00347     }
00348 
00349     wxRect rect = event.GetRect();
00350 
00351     // account for the resize sash size when converting to and from absolute and background coords
00352     if( event.GetSourceCoords() == IFM_COORDS_ABSOLUTE && event.GetDestinationCoords() == IFM_COORDS_BACKGROUND )
00353     {
00354         switch(data->m_side)
00355         {
00356             case IFM_ORIENTATION_LEFT:
00357                 rect.x += IFM_RESIZE_SASH_SIZE;
00358                 rect.width -= IFM_RESIZE_SASH_SIZE;
00359                 break;
00360 
00361             case IFM_ORIENTATION_RIGHT:
00362                 rect.width -= IFM_RESIZE_SASH_SIZE;
00363                 break;
00364 
00365             case IFM_ORIENTATION_TOP:
00366                 rect.y += IFM_RESIZE_SASH_SIZE;
00367                 rect.height -= IFM_RESIZE_SASH_SIZE;
00368                 break;
00369 
00370             case IFM_ORIENTATION_BOTTOM:
00371                 rect.height -= IFM_RESIZE_SASH_SIZE;
00372                 break;
00373         }
00374     }
00375     else if (event.GetSourceCoords() == IFM_COORDS_BACKGROUND && event.GetDestinationCoords() == IFM_COORDS_ABSOLUTE )
00376     {
00377         switch(data->m_side)
00378         {
00379             case IFM_ORIENTATION_LEFT:
00380                 rect.x -= IFM_RESIZE_SASH_SIZE;
00381                 rect.width += IFM_RESIZE_SASH_SIZE;
00382                 break;
00383 
00384             case IFM_ORIENTATION_RIGHT:
00385                 rect.width += IFM_RESIZE_SASH_SIZE;
00386                 break;
00387 
00388             case IFM_ORIENTATION_TOP:
00389                 rect.y -= IFM_RESIZE_SASH_SIZE;
00390                 rect.height += IFM_RESIZE_SASH_SIZE;
00391                 break;
00392 
00393             case IFM_ORIENTATION_BOTTOM:
00394                 rect.height += IFM_RESIZE_SASH_SIZE;
00395                 break;
00396         }
00397     }
00398 
00399     event.SetRect(rect);
00400 
00401     // default processing
00402     event.Skip();
00403 }
00404 
00405 void wxIFMDefaultResizePlugin::OnPaintDecor(wxIFMPaintEvent &event)
00406 {
00407     wxIFMComponent *component = event.GetComponent();
00408     wxIFMResizeData *data = IFM_GET_EXTENSION_DATA(component, wxIFMResizeData);
00409 
00410     // paint a resize sash if it is visible
00411     if( data->m_display && !component->m_hidden )
00412     {
00413         // get resize sash rect
00414         wxIFMRectEvent rectevt(wxEVT_IFM_GETRESIZESASHRECT, component);
00415         GetIP()->ProcessPluginEvent(rectevt);
00416         wxRect sash_rect = rectevt.GetRect();
00417 
00419         wxBrush brush_bg(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
00420         wxPen pen_bg(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
00421         wxPen border_pen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW));
00422 
00423         wxDC &dc = event.GetDC();
00424 
00425         dc.BeginDrawing();
00426 
00427         // paint background
00428         dc.SetBrush(brush_bg);
00429         dc.SetPen(pen_bg);
00430         dc.DrawRectangle(sash_rect);
00431 
00432         // paint borders
00433         dc.SetPen(border_pen);
00434 
00435         // borders on the top and bottom sides only paint top and bottom borders
00436         // left and right sides paint left and right borders
00437 #if IFM_RESIZE_SASH_BORDER
00438         switch(data->m_side)
00439         {
00440         case IFM_ORIENTATION_LEFT:
00441         case IFM_ORIENTATION_RIGHT:
00442             dc.DrawLine(sash_rect.x + sash_rect.width - 1, sash_rect.y, sash_rect.x + sash_rect.width - 1, sash_rect.y + sash_rect.height);
00443             dc.DrawLine(sash_rect.x, sash_rect.y, sash_rect.x, sash_rect.y + sash_rect.height);
00444             break;
00445         case IFM_ORIENTATION_TOP:
00446         case IFM_ORIENTATION_BOTTOM:
00447             dc.DrawLine(sash_rect.x, sash_rect.y, sash_rect.x + sash_rect.width, sash_rect.y);
00448             dc.DrawLine(sash_rect.x, sash_rect.y + sash_rect.height - 1, sash_rect.x + sash_rect.width, sash_rect.y + sash_rect.height - 1);
00449             break;
00450         }
00451 #endif
00452 
00453         dc.EndDrawing();
00454     }
00455 
00456     event.Skip();
00457 }
00458 
00459 void wxIFMDefaultResizePlugin::OnGetRect(wxIFMRectEvent &event)
00460 {
00461     if( event.GetEventType() != wxEVT_IFM_GETRESIZESASHRECT )
00462     {
00463         event.Skip();
00464         return;
00465     }
00466 
00467     wxIFMComponent *component = event.GetComponent();
00468     wxIFMResizeData *data = IFM_GET_EXTENSION_DATA(component, wxIFMResizeData);
00469     if( !data->m_display || component->m_hidden )
00470         return;
00471 
00472     event.SetRect(data->m_rect);
00473 }
00474 
00475 void wxIFMDefaultResizePlugin::OnSetRect(wxIFMRectEvent &event)
00476 {
00477     if( event.GetEventType() != wxEVT_IFM_SETRECT )
00478     {
00479         event.Skip();
00480         return;
00481     }
00482 
00483     // default processing
00484     GetNextHandler()->ProcessEvent(event);
00485 
00486     // set the resize sash as well
00487     wxIFMComponent *component = event.GetComponent();
00488     wxIFMResizeData *data = IFM_GET_EXTENSION_DATA(component, wxIFMResizeData);
00489     wxRect component_rect = event.GetRect(), sash_rect;
00490 
00491     // calculate resize sash rect
00492     switch(data->m_side)
00493     {
00494         case IFM_ORIENTATION_LEFT:
00495             sash_rect.x = component_rect.x;
00496             sash_rect.y = component_rect.y;
00497             sash_rect.width = IFM_RESIZE_SASH_SIZE;
00498             sash_rect.height = component_rect.height;
00499             break;
00500 
00501         case IFM_ORIENTATION_TOP:
00502             sash_rect.x = component_rect.x;
00503             sash_rect.y = component_rect.y;
00504             sash_rect.width = component_rect.width;
00505             sash_rect.height = IFM_RESIZE_SASH_SIZE;
00506             break;
00507 
00508         case IFM_ORIENTATION_RIGHT:
00509             sash_rect.x = component_rect.x + component_rect.width - IFM_RESIZE_SASH_SIZE;
00510             sash_rect.y = component_rect.y;
00511             sash_rect.width = IFM_RESIZE_SASH_SIZE;
00512             sash_rect.height = component_rect.height;
00513             break;
00514 
00515         case IFM_ORIENTATION_BOTTOM:
00516             sash_rect.x = component_rect.x;
00517             sash_rect.y = component_rect.y + component_rect.height - IFM_RESIZE_SASH_SIZE;
00518             sash_rect.height = IFM_RESIZE_SASH_SIZE;
00519             sash_rect.width = component_rect.width;
00520             break;
00521     }
00522 
00523     data->m_rect = sash_rect;
00524 }
00525 
00526 void wxIFMDefaultResizePlugin::OnSetCursor(wxIFMSetCursorEvent &event)
00527 {
00528     wxIFMComponent *component = event.GetComponent();
00529 
00530     if( component )
00531     {
00532         wxSetCursorEvent &cursor_event = event.GetCursorEvent();
00533         wxPoint pos = wxPoint(cursor_event.GetX(), cursor_event.GetY());
00534 
00535         wxIFMRectEvent evt(wxEVT_IFM_GETRESIZESASHRECT, component);
00536         GetIP()->ProcessPluginEvent(evt);
00537 
00538         if( evt.GetRect().Inside(pos) )
00539         {
00540             wxIFMResizeData *data = IFM_GET_EXTENSION_DATA(component, wxIFMResizeData);
00541             switch(data->m_side)
00542             {
00543                 case IFM_ORIENTATION_TOP:
00544                 case IFM_ORIENTATION_BOTTOM:
00545                     cursor_event.SetCursor(wxCursor(wxCURSOR_SIZENS));
00546                     break;
00547                 case IFM_ORIENTATION_LEFT:
00548                 case IFM_ORIENTATION_RIGHT:
00549                     cursor_event.SetCursor(wxCursor(wxCURSOR_SIZEWE));
00550                     break;
00551             }
00552             return;
00553         }
00554     }
00555 
00556     event.Skip();
00557 }
00558 
00559 void wxIFMDefaultResizePlugin::OnLeftDown(wxIFMMouseEvent &event)
00560 {
00561     wxIFMComponent *component = event.GetComponent();
00562 
00563     if( !component )
00564     {
00565         event.Skip();
00566         return;
00567     }
00568 
00570     wxIFMRectEvent rectevt(wxEVT_IFM_GETRESIZESASHRECT, component);
00571     GetIP()->ProcessPluginEvent(rectevt);
00572     wxRect resize_rect = rectevt.GetRect();
00573 
00574     if( !resize_rect.Inside(event.GetMouseEvent().GetPosition()) )
00575     {
00576         event.Skip();
00577         return;
00578     }
00579 
00580     if( !m_resizing )
00581     {
00582         GetManager()->CaptureInput(component);
00583         GetManager()->GetCapturedWindow()->SetFocus();
00584         m_resizing = true;
00585 
00586         wxIFMResizeEvent evt(wxEVT_IFM_BEGINRESIZE, component,
00587             event.GetMouseEvent().GetPosition(), m_realtime);
00588         GetIP()->ProcessPluginEvent(evt);
00589     }
00590 }
00591 
00592 void wxIFMDefaultResizePlugin::OnLeftUp(wxIFMMouseEvent &event)
00593 {
00594     if( m_resizing  )
00595     {
00596         m_resizing = false;
00597         GetManager()->ReleaseInput();
00598 
00599         wxIFMResizeEvent evt(wxEVT_IFM_ENDRESIZE, event.GetComponent(),
00600             event.GetMouseEvent().GetPosition(), m_realtime);
00601         GetIP()->ProcessPluginEvent(evt);
00602     }
00603     else
00604         event.Skip();
00605 }
00606 
00607 void wxIFMDefaultResizePlugin::OnMouseMove(wxIFMMouseEvent &event)
00608 {
00609     if( m_resizing )
00610     {
00611         wxIFMResizeEvent evt(wxEVT_IFM_RESIZE, event.GetComponent(),
00612             event.GetMouseEvent().GetPosition(), m_realtime);
00613         GetIP()->ProcessPluginEvent(evt);
00614     }
00615     else
00616         event.Skip();
00617 }
00618 
00619 void wxIFMDefaultResizePlugin::OnKeyDown(wxIFMKeyEvent &event)
00620 {
00621     if( m_resizing )
00622     {
00623         if( event.GetKeyEvent().GetKeyCode() == WXK_ESCAPE )
00624         {
00625             wxIFMResizeEvent evt(wxEVT_IFM_ENDRESIZE, event.GetComponent(),
00626                 event.GetKeyEvent().GetPosition(), m_realtime, true);
00627             if( GetIP()->ProcessPluginEvent(evt) )
00628             {
00629                 m_resizing = false;
00630                 GetManager()->ReleaseInput();
00631             }
00632         }
00633     }
00634 }
00635 
00636 void wxIFMDefaultResizePlugin::PaintResizeHint(wxScreenDC &dc, const wxRect &rect)
00637 {
00638     dc.SetBrush(*wxGREY_BRUSH);
00639     dc.SetPen(*wxGREY_PEN);
00640 
00641     dc.SetLogicalFunction(wxXOR);
00642     dc.DrawRectangle(rect);
00643 
00644     dc.SetPen(wxNullPen);
00645     dc.SetBrush(wxNullBrush);
00646 }
00647 
00648 void wxIFMDefaultResizePlugin::OnResizeBegin(wxIFMResizeEvent &event)
00649 {
00650     wxIFMComponent *component = event.GetComponent();
00651     wxPoint pos = event.GetPosition();
00652 
00653     wxIFMRectEvent rectevt(wxEVT_IFM_GETRESIZESASHRECT, component);
00654     GetIP()->ProcessPluginEvent(rectevt);
00655     wxRect resize_rect = rectevt.GetRect();
00656 
00657     wxIFMResizeData *data = IFM_GET_EXTENSION_DATA(component, wxIFMResizeData);
00658     switch(data->m_side)
00659     {
00660         case IFM_ORIENTATION_LEFT:
00661         case IFM_ORIENTATION_RIGHT:
00662             m_orientation = IFM_ALIGN_VERTICAL;
00663             pos.y = resize_rect.y;
00664             m_offset = pos.x - resize_rect.x;
00665             pos.x -= m_offset;
00666             break;
00667         case IFM_ORIENTATION_TOP:
00668         case IFM_ORIENTATION_BOTTOM:
00669             m_orientation = IFM_ALIGN_HORIZONTAL;
00670             pos.x = resize_rect.x;
00671             m_offset = pos.y - resize_rect.y;
00672             pos.y -= m_offset;
00673             break;
00674     }
00675 
00676     m_oldPos = GetManager()->GetCapturedWindow()->ClientToScreen(pos);
00677     m_resizeRect = wxRect(m_oldPos, rectevt.GetSize());
00678 
00679     if( !event.RealtimeUpdates() )
00680     {
00681         wxScreenDC dc;
00682         PaintResizeHint(dc, m_resizeRect);
00683     }
00684 }
00685 
00686 void wxIFMDefaultResizePlugin::OnResizeEnd(wxIFMResizeEvent &event)
00687 {
00688     if( !event.RealtimeUpdates() )
00689     {
00690         // unpaint resize hint
00691         wxScreenDC dc;
00692         PaintResizeHint(dc, m_resizeRect);
00693     }
00694 
00695     if( !event.WasCanceled() )
00696     {
00697         wxIFMComponent *component = event.GetComponent();
00698 
00699         wxIFMResizeData *resize_data = IFM_GET_EXTENSION_DATA(component, wxIFMResizeData);
00700 
00701         wxPoint pos = event.GetPosition();
00702 
00703         if( m_orientation == IFM_ALIGN_HORIZONTAL )
00704         {
00705             pos.y -= m_offset;
00706             pos.x = m_resizeRect.x;
00707         }
00708         else if( m_orientation == IFM_ALIGN_VERTICAL )
00709         {
00710             pos.x -= m_offset;
00711             pos.y = m_resizeRect.y;
00712         }
00713 
00714         // accessing m_rect directly here is OK because we know the component cannot be hidden
00715         wxRect rect = component->m_rect;
00716         int new_width = 0, new_height = 0;
00717 
00718         switch(resize_data->m_side)
00719         {
00720             case IFM_ORIENTATION_BOTTOM:
00721                 new_width = rect.width;
00722                 new_height = pos.y - rect.y + IFM_RESIZE_SASH_SIZE;
00723                 break;
00724             case IFM_ORIENTATION_TOP:
00725                 new_width = rect.width;
00726                 new_height = rect.y + rect.height - pos.y;
00727                 break;
00728             case IFM_ORIENTATION_LEFT:
00729                 new_height = rect.height;
00730                 new_width = rect.x + rect.width - pos.x;
00731                 break;
00732             case IFM_ORIENTATION_RIGHT:
00733                 new_height = rect.height;
00734                 new_width = pos.x - rect.x + IFM_RESIZE_SASH_SIZE;
00735                 break;
00736         }
00737 
00738         wxSize size(new_width, new_height);
00739 
00740         if( component->m_docked )
00741         {
00742             // set the desired size of the component and its siblings to make room
00743             ResizeComponent(component, size);
00744         }
00745         else
00746         {
00747             // just update the component
00748             wxIFMRectEvent setevt(wxEVT_IFM_SETDESIREDSIZE, component, wxPoint(), size);
00749             GetIP()->ProcessPluginEvent(setevt);
00750         }
00751 
00752         // only update the parent container to save updating the entire interface if we can get away with it
00753         wxIFMComponent *parent = component->m_parent;
00754         if( parent )
00755         {
00756             wxIFMUpdateComponentEvent evt(parent, parent->GetRect());
00757             GetIP()->ProcessPluginEvent(evt);
00758         }
00759         else
00760             GetManager()->Update();
00761     }
00762 }
00763 
00764 void wxIFMDefaultResizePlugin::ResizeComponent(wxIFMComponent *component, wxSize size)
00765 {
00766     wxIFMComponent *parent = component->m_parent;
00767 
00768     if( parent->GetType() != IFM_COMPONENT_CONTAINER )
00769         return;
00770 
00771     // set our desired size first
00772     wxIFMRectEvent setevt(wxEVT_IFM_SETDESIREDSIZE, component, wxPoint(), size);
00773     GetIP()->ProcessPluginEvent(setevt);
00774 
00775     // set the desired size of our siblings
00776     wxIFMComponentArray &children = parent->m_children;
00777     wxRect parent_rect;
00778     int numchildren = children.size(), i;
00779 
00780     parent_rect = parent->GetClientRect();
00781 
00782     // find the index of the thing we resized in its parent
00783     int index = 0;
00784     for( i = 0; i < numchildren; ++i )
00785     {
00786         if( children[i] == component )
00787         {
00788             index = i;
00789             break;
00790         }
00791     }
00792 
00793     // calculate the available parent rect to use for component rect calculations
00794     for( i = 0; i <= index; ++i )
00795     {
00796         const wxRect &rect = (i == index) ? wxRect(wxPoint(), size) : children[i]->GetRect();
00797 
00798         if( parent->m_alignment == IFM_ALIGN_HORIZONTAL )
00799         {
00800             parent_rect.width -= rect.width;
00801             parent_rect.x += rect.width;
00802         }
00803         else
00804         {
00805             parent_rect.height -= rect.height;
00806             parent_rect.y += rect.height;
00807         }
00808     }
00809 
00810     // add the children that require sizing to the parent rect
00811     wxIFMCalcRectsEvent calcevt(parent, parent_rect);
00812 
00813     for( i = index + 1; i < numchildren; ++i )
00814         calcevt.AddComponent(children[i]);
00815 
00816     GetIP()->ProcessPluginEvent(calcevt);
00817 
00818     // set children desired sizes
00819     const wxRectArray &rects = calcevt.GetComponentRects();
00820     for( i = 0; i < numchildren; ++i )
00821     {
00822         wxRect rect;
00823 
00824         if( i < index )
00825             rect = children[i]->GetRect();
00826         else if( i == index )
00827             continue;
00828         else
00829             rect = rects[i - index - 1];
00830 
00831         wxIFMRectEvent evt(wxEVT_IFM_SETDESIREDSIZE, children[i], rect);
00832         GetIP()->ProcessPluginEvent(evt);
00833     }
00834 }
00835 
00836 void wxIFMDefaultResizePlugin::OnResizing(wxIFMResizeEvent &event)
00837 {
00838     wxPoint pos = GetManager()->GetCapturedWindow()->ClientToScreen(event.GetPosition());
00839 
00840     if( m_orientation == IFM_ALIGN_HORIZONTAL )
00841     {
00842         pos.y -= m_offset;
00843         pos.x = m_resizeRect.x;
00844     }
00845     else if( m_orientation == IFM_ALIGN_VERTICAL )
00846     {
00847         pos.x -= m_offset;
00848         pos.y = m_resizeRect.y;
00849     }
00850 
00851     if( !event.RealtimeUpdates() )
00852     {
00853         // draw resize sash
00854         wxScreenDC dc;
00855 
00856         m_resizeRect.SetPosition(m_oldPos);
00857         PaintResizeHint(dc, m_resizeRect);
00858         m_resizeRect.SetPosition(pos);
00859         PaintResizeHint(dc, m_resizeRect);
00860     }
00861 
00862     m_oldPos = pos;
00863 }
00864 
00865 bool wxIFMDefaultResizePlugin::HasResizeableChildren(wxIFMComponent *component)
00866 {
00867     wxIFMComponent *child;
00868 
00869     const wxIFMComponentArray &children = component->m_children;
00870     for( int i = 0, count = children.GetCount(); i < count; ++i )
00871     //for( wxIFMComponentArray::const_iterator i = children.begin(), end = children.end(); i != end; ++i )
00872     {
00873         child = children[i];
00874         //child = *i;
00875 
00876         if( child->GetType() != IFM_COMPONENT_CONTAINER )
00877         {
00878             if( !child->m_fixed )
00879                 return true;
00880         }
00881 
00882         if( !child->m_fixed )
00883         {
00884             // check children
00885             if( HasResizeableChildren(child) )
00886                 return true;
00887         }
00888     }
00889 
00890     return false;
00891 }
00892 
00893 /*
00894 wxIFMResizeData implementation
00895 */
00896 wxIFMResizeData::wxIFMResizeData()
00897     : wxIFMExtensionDataBase(),
00898     m_side(IFM_ORIENTATION_NONE),
00899     m_display(false)
00900 { }
00901 
00902 wxIFMComponentDataKeyType wxIFMResizeData::GetDataKey() const
00903 {
00904     return IFM_RESIZE_DATA_KEY;
00905 }
00906 
00907 wxIFMComponentDataKeyType wxIFMResizeData::DataKey()
00908 {
00909     return IFM_RESIZE_DATA_KEY;
00910 }

 

SourceForge Logo