MatOCAD Logo

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

definterface.cpp

Go to the documentation of this file.
00001 
00012 #include "../../include/wxIFM/definterface.h"
00013 #include "../../include/wxIFM/resize.h"
00014 #include "../../include/wxIFM/dragndrop.h"
00015 #include <wx/panel.h>
00016 
00017 #include "../../icons/btn_hide.xpm"
00018 #include "../../icons/btn_min.xpm"
00019 #include "../../icons/btn_max.xpm"
00020 #include "../../icons/btn_hide_h.xpm"
00021 #include "../../icons/btn_min_h.xpm"
00022 #include "../../icons/btn_max_h.xpm"
00023 #include "../../icons/btn_hide_hp.xpm"
00024 #include "../../icons/btn_min_hp.xpm"
00025 #include "../../icons/btn_max_hp.xpm"
00026 
00027 #include <wx/settings.h>
00028 
00029 #include <wx/listimpl.cpp>
00030 WX_DEFINE_LIST(wxIFMComponentList);
00031 
00032 DEFINE_IFM_DATA_KEY(IFM_CONTAINER_DATA_KEY)
00033 DEFINE_IFM_DATA_KEY(IFM_PANEL_DATA_KEY)
00034 DEFINE_IFM_DATA_KEY(IFM_TABBED_PANEL_DATA_KEY)
00035 
00036 DEFINE_IFM_COMPONENT_TYPE(IFM_COMPONENT_CONTAINER)
00037 DEFINE_IFM_COMPONENT_TYPE(IFM_COMPONENT_PANEL_TAB)
00038 DEFINE_IFM_COMPONENT_TYPE(IFM_COMPONENT_PANEL)
00039 
00040 DEFINE_EVENT_TYPE(wxEVT_IFM_ADDTOPCONTAINER);
00041 DEFINE_EVENT_TYPE(wxEVT_IFM_REMOVETOPCONTAINER);
00042 DEFINE_EVENT_TYPE(wxEVT_IFM_SELECTTAB);
00043 DEFINE_EVENT_TYPE(wxEVT_IFM_COMPONENTBUTTONCLICK);
00044 
00045 #if IFM_USE_WX_RTTI
00046 IMPLEMENT_DYNAMIC_CLASS(wxIFMDefaultInterfacePlugin, wxIFMInterfacePluginBase);
00047 IMPLEMENT_DYNAMIC_CLASS(wxIFMDefaultContainerPlugin, wxIFMExtensionPluginBase);
00048 IMPLEMENT_DYNAMIC_CLASS(wxIFMDefaultPanelPlugin, wxIFMExtensionPluginBase);
00049 IMPLEMENT_DYNAMIC_CLASS(wxIFMDefaultChildData, wxIFMChildDataBase);
00050 IMPLEMENT_DYNAMIC_CLASS(wxIFMContainerData, wxIFMExtensionDataBase);
00051 IMPLEMENT_DYNAMIC_CLASS(wxIFMPanelTabData, wxIFMExtensionDataBase);
00052 IMPLEMENT_DYNAMIC_CLASS(wxIFMPanelData, wxIFMExtensionDataBase);
00053 #endif
00054 
00055 // bitmaps for component buttons
00056 wxBitmap m_bmpClose, m_bmpMin, m_bmpMax,
00057     m_bmpCloseH, m_bmpMinH, m_bmpMaxH,
00058     m_bmpCloseP, m_bmpMinP, m_bmpMaxP;
00059 
00060 #if IFM_CANFLOAT
00061 
00062 /*
00063 wxIFMFloatingFrame implementation
00064 */
00065 BEGIN_EVENT_TABLE(wxIFMFloatingFrame, wxIFMFloatingWindowBase)
00066     EVT_CLOSE   (wxIFMFloatingFrame::OnClose)
00067 END_EVENT_TABLE()
00068 
00069 wxIFMFloatingFrame::wxIFMFloatingFrame(wxIFMInterfacePluginBase *ip, wxWindow *parent, wxWindowID id,
00070         const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
00071         : wxIFMFloatingWindowBase(ip)
00072 {
00073     m_window = new wxFrame(parent, id, title, pos, size, style, name);
00074     ConnectEvents();
00075 }
00076 
00077 void wxIFMFloatingFrame::OnClose(wxCloseEvent &event)
00078 {
00079     // don't know if this works, but at least try to close properly
00080     // if we can't veto the event
00081     if( event.CanVeto() )
00082     {
00083         // only hide the window
00084         event.Veto();
00085         m_window->Hide();
00086 
00087         // hide our root component too
00088         m_component->Show(false, false);
00089     }
00090     else
00091     {
00092         DisconnectEvents();
00093     }
00094 }
00095 
00096 #endif
00097 
00098 /*
00099 wxIFMDefaultInterfacePlugin implementation
00100 */
00101 BEGIN_EVENT_TABLE(wxIFMDefaultInterfacePlugin, wxIFMInterfacePluginBase)
00102     EVT_IFM_DELETECOMPONENT (wxIFMDefaultInterfacePlugin::OnDeleteComponent)
00103     EVT_IFM_ADDCHILD    (wxIFMDefaultInterfacePlugin::OnAddChild)
00104     EVT_IFM_UPDATE      (wxIFMDefaultInterfacePlugin::OnUpdate)
00105     EVT_IFM_PAINTINTERFACE (wxIFMDefaultInterfacePlugin::OnPaint)
00106     EVT_IFM_GETCONTENTRECT(wxIFMDefaultInterfacePlugin::OnGetContentRect)
00107 
00108     EVT_IFM_ADDTOPCONTAINER (wxIFMDefaultInterfacePlugin::OnAddTopContainer)
00109     EVT_IFM_REMOVETOPCONTAINER (wxIFMDefaultInterfacePlugin::OnRemoveTopContainer)
00110 
00111 #if IFM_CANFLOAT
00112     EVT_IFM_CREATEFLOATINGWINDOW    (wxIFMDefaultInterfacePlugin::OnCreateFloatingWindow)
00113     EVT_IFM_DESTROYFLOATINGWINDOW   (wxIFMDefaultInterfacePlugin::OnDestroyFloatingWindow)
00114     //EVT_IFM_FLOAT                   (wxIFMDefaultInterfacePlugin::OnFloat)
00115 #endif
00116 END_EVENT_TABLE()
00117 
00118 wxIFMDefaultInterfacePlugin::wxIFMDefaultInterfacePlugin()
00119     : wxIFMInterfacePluginBase()
00120 { }
00121 
00122 wxIFMDefaultInterfacePlugin::~wxIFMDefaultInterfacePlugin()
00123 {
00124 #if IFM_CANFLOAT
00125     // delete floating window objects
00126     for( int i = 0, count = m_floatingWindows.GetCount(); i < count; ++i )
00127     //for( wxIFMFloatingWindowArray::const_iterator i = m_floatingWindows.begin(), end = m_floatingWindows.end(); i != end; ++i )
00128         delete m_floatingWindows[i];
00129         //delete (*i);
00130 #endif
00131 }
00132 
00133 const wxIFMComponentList &wxIFMDefaultInterfacePlugin::GetTopContainerList() const
00134 {
00135     return m_containers;
00136 }
00137 
00138 bool wxIFMDefaultInterfacePlugin::ProcessPluginEvent(wxIFMPluginEvent &event)
00139 {
00140     bool ret = wxIFMInterfacePluginBase::ProcessPluginEvent(event);
00141 
00142 #if IFM_CANFLOAT
00143     if( event.GetEventType() == wxEVT_IFM_CREATEFLOATINGWINDOW )
00144     {
00145 #if IFM_USE_WX_RTTI
00146         wxIFMCreateFloatingWindowEvent *evt = wxDynamicCast(&event, wxIFMCreateFloatingWindowEvent);
00147 #else
00148         wxIFMCreateFloatingWindowEvent *evt = dynamic_cast<wxIFMCreateFloatingWindowEvent*>(&event);
00149 #endif
00150         if( evt )
00151             m_floatingWindows.push_back(evt->GetWindow());
00152     }
00153 #endif
00154 
00155     return ret;
00156 }
00157 
00158 void wxIFMDefaultInterfacePlugin::OnAddTopContainer(wxIFMAddTopContainerEvent &event)
00159 {
00160     wxIFMComponent *component = event.GetComponent();
00161 
00162     wxASSERT_MSG(component, wxT("NULL component?"));
00163     if( !component )
00164         return;
00165 
00166     if( event.GetIndexMode() )
00167     {
00168         int index = event.GetIndex();
00169 
00170         if( index == -1 )
00171         {
00172             m_containers.push_back(component);
00173         }
00174         else
00175         {
00176             // get an interator to the index position
00177             if( index == 0 )
00178                 m_containers.push_front(component);
00179             else
00180             {
00181                 wxIFMComponentList::iterator i; int n;
00182                 for( i = m_containers.begin(), n = 0; n < index; ++i, n++ );
00183                 m_containers.insert(i, component);
00184             }
00185         }
00186     }
00187     else
00188     {
00189         // find the index of the index container
00190         wxIFMComponent *index = event.GetIndexContainer();
00191         wxIFMComponentList::iterator i, end;
00192         for( i = m_containers.begin(), end = m_containers.end(); i != end; ++i)
00193         {
00194             if( *i == index )
00195                 break;
00196         }
00197 
00198         // dock before or after this index
00199         if( !event.GetIndex() ) // GetIndex() == 0 means dock after
00200             i++;
00201         // dont advance to the end of the list
00202         if( i == end )
00203             m_containers.push_back(component);
00204         else
00205             m_containers.insert(i, component);
00206     }
00207 
00208 #if IFM_CANFLOAT
00209     // if a container is moved from a floating window into a top level position, it needs
00210     // to recieve float notify events, or child windows fall off the face of the earth
00211     wxIFMFloatNotifyEvent evt(component, false);
00212     ProcessPluginEvent(evt);
00213 #endif
00214 }
00215 
00216 void wxIFMDefaultInterfacePlugin::OnRemoveTopContainer(wxIFMRemoveTopContainerEvent &event)
00217 {
00218     wxIFMComponent *container = event.GetComponent();
00219 
00220     wxASSERT_MSG(container, wxT("NULL component?"));
00221     if( !container )
00222         return;
00223 
00224     for( wxIFMComponentList::iterator i = m_containers.begin(), end = m_containers.end(); i != end; ++i )
00225     {
00226         if( *i == container )
00227         {
00228             m_containers.erase(i);
00229 
00230             // give the container no orientation value
00231             wxIFMContainerData *data = IFM_GET_EXTENSION_DATA(container, wxIFMContainerData);
00232             wxASSERT_MSG(data, wxT("Container with no container data?"));
00233             if( data )
00234                 data->m_orientation = IFM_ORIENTATION_NONE;
00235 
00236             return;
00237         }
00238     }
00239 
00240     wxFAIL_MSG(wxT("Trying to remove a container not in top level list!"));
00241 }
00242 
00243 bool wxIFMDefaultInterfacePlugin::Initialize(wxInterfaceManager *m_manager)
00244 {
00245     // base initialization
00246     wxIFMInterfacePluginBase::Initialize(m_manager);
00247 
00248     // push required plugins
00249     wxIFMExtensionPluginBase *plugin;
00250 
00251     plugin = new wxIFMDefaultContainerPlugin();
00252     if( !PushExtensionPlugin(plugin) )
00253         return false;
00254 
00255     plugin = new wxIFMDefaultPanelPlugin();
00256     if( !PushExtensionPlugin(plugin) )
00257         return false;
00258 
00259     plugin = new wxIFMDefaultResizePlugin();
00260     if( !PushExtensionPlugin(plugin) )
00261         return false;
00262 
00263     plugin = new wxIFMDefaultDockingPlugin();
00264     if( !PushExtensionPlugin(plugin) )
00265         return false;
00266 
00267     return true;
00268 }
00269 
00270 wxIFMComponent *wxIFMDefaultInterfacePlugin::GetContainer(int orientation)
00271 {
00272     // look for the last container with the specified orientation
00273     // FIXME: This actually finds the first container?
00274     //for( wxIFMComponentList::compatibility_iterator node = m_containers.GetFirst(); node; node = node->GetNext() )
00275     for( wxIFMComponentList::const_iterator i = m_containers.begin(), end = m_containers.end(); i != end; ++i )
00276     {
00277         //wxIFMComponent *container = node->GetData();
00278         wxIFMComponent *container = (*i);
00279         wxIFMContainerData *data = IFM_GET_EXTENSION_DATA(container, wxIFMContainerData);
00280         if( data->m_orientation == orientation )
00281             return container;
00282     }
00283 
00284     // no container found
00285     return NULL;
00286 }
00287 
00288 void wxIFMDefaultInterfacePlugin::OnDeleteComponent(wxIFMDeleteComponentEvent &event)
00289 {
00290     if( event.GetComponentType() == IFM_COMPONENT_CONTAINER )
00291     {
00292         wxIFMComponent *container = event.GetComponent();
00293 
00294         // remove the container from the top level container list
00295         for( wxIFMComponentList::iterator i = m_containers.begin(), end = m_containers.end(); i != end; ++i )
00296         {
00297             if( *i == container )
00298             {
00299                 m_containers.erase(i);
00300                 break;
00301             }
00302         }
00303     }
00304 
00305     event.Skip();
00306 }
00307 
00308 void wxIFMDefaultInterfacePlugin::OnAddChild(wxIFMAddChildEvent &event)
00309 {
00310     static int s_nextOrientation = IFM_ORIENTATION_TOP; // for default orientation selection
00311     static wxIFMComponent *last_panel;
00312     bool delete_data = false;
00313 
00314     wxIFMChildDataBase *base = event.GetChildData();
00315 
00316     // verify that the data is of the right type
00317 #if IFM_USE_WX_RTTI
00318     wxIFMDefaultChildData *data = wxDynamicCast(base, wxIFMDefaultChildData);
00319 #else
00320     wxIFMDefaultChildData *data = dynamic_cast<wxIFMDefaultChildData*>(base);
00321 #endif
00322 
00323     // construct a defaultchilddata object from the regular object if we must
00324     if( !data )
00325     {
00326         delete_data = true;
00327         data = new wxIFMDefaultChildData(*base);
00328     }
00329 
00331     bool tabify = data->m_tabify;
00332 
00333     // create a tab for the child
00334     wxIFMNewComponentEvent newevt(IFM_COMPONENT_PANEL_TAB);
00335     ProcessPluginEvent(newevt);
00336 
00337     wxIFMComponent *tab = newevt.GetComponent();
00338 
00339     tab->m_canHide = data->m_hideable;
00340     tab->m_fixed = data->m_fixed;
00341 
00342     if( !tab->m_fixed )
00343     {
00344         tab->m_minSize = data->m_minSize;
00345         tab->m_maxSize = data->m_maxSize;
00346         tab->m_desiredSize = data->m_desiredSize;
00347     }
00348     else
00349         tab->m_minSize = (tab->m_maxSize = (tab->m_desiredSize = data->m_desiredSize));
00350 
00351 #if IFM_CANFLOAT
00352     // set floating data for the tab and the tabbed panel
00353     wxIFMFloatingData *floating_data = IFM_GET_EXTENSION_DATA(tab, wxIFMFloatingData);
00354     floating_data->m_rect.SetSize(tab->m_desiredSize);
00355     floating_data->m_rect.SetPosition(data->m_pos);
00356 #endif
00357 
00358     tab->m_name = data->m_name;
00359 
00360     wxIFMPanelTabData *tab_data = IFM_GET_EXTENSION_DATA(tab, wxIFMPanelTabData);
00361     if(data->m_bitmap.Ok())
00362         tab_data->m_bitmap = data->m_bitmap.GetSubBitmap(wxRect(0, 0, data->m_bitmap.GetWidth(), data->m_bitmap.GetHeight()));
00363 
00364     // set the child of the tab
00365     wxIFMSetChildEvent setevt(tab, data->m_type, data->m_child);
00366     ProcessPluginEvent(setevt);
00367 
00368     // store the child window / component pair
00369     AddChildWindow(data->m_child, tab);
00370 
00371     int orientation = data->m_orientation;
00372 
00373     // are we floating?
00374 #if IFM_CANFLOAT
00375     if( orientation == IFM_ORIENTATION_FLOAT )
00376     {
00377         // send the tab a float event
00378         wxIFMFloatEvent floatevt(tab, floating_data->m_rect);
00379         ProcessPluginEvent(floatevt);
00380     }
00381     else
00382 #endif
00383     // handle tabify
00384     if( tabify && last_panel )
00385     {
00386         // dock the child as a tab of the last panel
00387         wxIFMDockEvent evt(tab, last_panel, IFM_DEFAULT_INDEX);
00388         ProcessPluginEvent(evt);
00389     }
00390     else
00391     {
00392         // see if we need to chose an orientation
00393         if( orientation == IFM_ORIENTATION_DEFAULT )
00394         {
00395             orientation = s_nextOrientation;
00396 
00397             // calculate next orientation
00398             switch(s_nextOrientation)
00399             {
00400                 case IFM_ORIENTATION_TOP:
00401                     s_nextOrientation = IFM_ORIENTATION_LEFT;
00402                     break;
00403                 case IFM_ORIENTATION_LEFT:
00404                     s_nextOrientation = IFM_ORIENTATION_BOTTOM;
00405                     break;
00406                 case IFM_ORIENTATION_BOTTOM:
00407                     s_nextOrientation = IFM_ORIENTATION_RIGHT;
00408                     break;
00409                 case IFM_ORIENTATION_RIGHT:
00410                     s_nextOrientation = IFM_ORIENTATION_TOP;
00411                     break;
00412             }
00413         }
00414 
00415         // retrieve destinition container
00416         wxIFMComponent *container = GetContainer(orientation);
00417 
00418         // make a container if need be
00419         if( !container || data->m_newRow )
00420         {
00421             wxIFMNewComponentEvent newevt(IFM_COMPONENT_CONTAINER);
00422             ProcessPluginEvent(newevt);
00423 
00424             container = newevt.GetComponent();
00425 
00426             wxASSERT_MSG(container, wxT("NULL component returned by new component event?"));
00427             if( !container )
00428                 return;
00429 
00430             wxIFMContainerData *data = IFM_GET_EXTENSION_DATA(container, wxIFMContainerData);
00431             wxASSERT_MSG(data, wxT("Container without container data?"));
00432             if( !data )
00433                 return;
00434 
00435             data->m_orientation = orientation;
00436             switch(orientation)
00437             {
00438                 case IFM_ORIENTATION_TOP:
00439                 case IFM_ORIENTATION_BOTTOM:
00440                     container->m_alignment = IFM_ALIGN_HORIZONTAL;
00441                     break;
00442                 case IFM_ORIENTATION_LEFT:
00443                 case IFM_ORIENTATION_RIGHT:
00444                     container->m_alignment = IFM_ALIGN_VERTICAL;
00445                     break;
00446             }
00447 
00448             // add container as a top level one using the event
00449             wxIFMAddTopContainerEvent addevt(container, -1);
00450             ProcessPluginEvent(addevt);
00451         }
00452 
00453         // dock this tabbed panel into the specified container
00454         wxIFMDockEvent dockevt(tab, container, data->m_index);
00455         ProcessPluginEvent(dockevt);
00456 
00457         // the tabs parent will be a panel automagically, so we store that
00458         // as the previously used panel for tabify
00459         last_panel = tab->m_parent;
00460     }
00461 
00462     // show or hide the new component
00463     tab->Show(!data->m_hidden, false);
00464 
00465     // complete successfully
00466     event.SetSuccess();
00467 
00468     if( delete_data )
00469         delete data;
00470 }
00471 
00472 void wxIFMDefaultInterfacePlugin::OnUpdate(wxIFMUpdateEvent &event)
00473 {
00474     wxSize size = event.GetSize();
00475     wxPoint pos = event.GetPosition();
00476     wxRect m_contentRect = event.GetRect();
00477 
00478     wxIFMComponent *container;
00479     wxIFMContainerData *data;
00480     wxWindow *content = event.GetContent();
00481     wxRect rect;
00482 
00483     int min_w = 0, min_h = 0;
00484 
00485     // update containers beginning from the start of the list
00486     // also calculate the minimum allowable size for the interface
00487     for( wxIFMComponentList::iterator i = m_containers.begin(), end = m_containers.end(); i != end; ++i )
00488     {
00489         container = *i;
00490 
00491         if( !container->IsVisible() )
00492             continue;
00493 
00494         data = IFM_GET_EXTENSION_DATA(container, wxIFMContainerData);
00495 
00496         // calculate size
00497         wxSize size = container->GetDesiredSize();
00498         wxSize min_size = container->GetMinSize();
00499 
00500         wxIFMComponentList::iterator temp = i;
00501         ++temp;
00502         if( temp == end && !content )
00503         {
00504             // make this container as big as the remaining area to deal with having no content window
00505             rect = m_contentRect;
00506         }
00507         else
00508         {
00509             switch(data->m_orientation)
00510             {
00511                 case IFM_ORIENTATION_LEFT:
00512                     rect.x = m_contentRect.x;
00513                     rect.y = m_contentRect.y;
00514                     rect.width = size.GetWidth();
00515                     rect.height = m_contentRect.height;
00516 
00517                     m_contentRect.width -= rect.width;
00518                     m_contentRect.x += rect.width;
00519 
00520                     //if( min_h < min_size.y )
00521                         min_h += min_size.y;
00522                         min_w += min_size.x;
00523 
00524                     break;
00525 
00526                 case IFM_ORIENTATION_RIGHT:
00527                     rect.width = size.GetWidth();
00528                     rect.x = m_contentRect.x + m_contentRect.width - rect.width;
00529                     rect.y = m_contentRect.y;
00530                     rect.height = m_contentRect.height;
00531 
00532                     m_contentRect.width -= rect.width;
00533 
00534                     //if( min_h < min_size.y )
00535                         min_h += min_size.y;
00536                         min_w += min_size.x;
00537 
00538                     break;
00539 
00540                 case IFM_ORIENTATION_TOP:
00541                     rect.x = m_contentRect.x;
00542                     rect.y = m_contentRect.y;
00543                     rect.width = m_contentRect.width;
00544                     rect.height = size.GetHeight();
00545 
00546                     m_contentRect.y += rect.height;
00547                     m_contentRect.height -= rect.height;
00548 
00549                     //if( min_w < min_size.x )
00550                         min_h += min_size.y;
00551                         min_w += min_size.x;
00552 
00553                     break;
00554 
00555                 case IFM_ORIENTATION_BOTTOM:
00556                     rect.width = m_contentRect.width;
00557                     rect.height = size.GetHeight();
00558                     rect.x = m_contentRect.x;
00559                     rect.y = m_contentRect.y + m_contentRect.height - rect.height;
00560 
00561                     m_contentRect.height -= rect.height;
00562 
00563                     //if( min_w < min_size.x )
00564                         min_h += min_size.y;
00565                         min_w += min_size.x;
00566 
00567                     break;
00568 
00569                 default:
00570                     wxFAIL_MSG(wxT("Invalid orientation value"));
00571             }
00572         }
00573 
00574         // this code is commented out because its logic is flawed
00575         // I need to not update a container so long as none of its children
00576         // require an update
00578         /*
00579         // only update the container if its new rect is different from its old rect
00580         wxIFMRectEvent rectevt(wxEVT_IFM_GETRECT, IFM_COMPONENT_CONTAINER, container);
00581         ProcessPluginEvent(rectevt);
00582 
00583         if( rect != rectevt.GetRect() )
00584         */
00585         {
00586             // update the container
00587             wxIFMUpdateComponentEvent updevt(container, rect);
00588             ProcessPluginEvent(updevt);
00589         }
00590     }
00591 
00592     // position content window
00593     if( content )
00594         content->SetSize(m_contentRect);
00595 
00596     // set size hints
00597     //GetManager()->GetParent()->ClientToScreen(&min_w, &min_h);
00598     GetManager()->GetParent()->SetSizeHints(min_w, min_h);
00599 
00600     // update floating windows if needed
00601 #if IFM_CANFLOAT
00602     if( event.GetFoating() )
00603     {
00604         wxIFMFloatingWindowBase *base;
00605 
00606         for( size_t i = 0; i < m_floatingWindows.GetCount(); i++ )
00607         //for( wxIFMFloatingWindowArray::const_iterator i = m_floatingWindows.begin(), end = m_floatingWindows.end(); i != end; ++i )
00608         {
00609             base = m_floatingWindows[i];
00610             // base = *i;
00611 
00612             base->Update(true);
00613         }
00614     }
00615 #endif
00616 }
00617 
00618 void wxIFMDefaultInterfacePlugin::OnPaint(wxIFMPaintInterfaceEvent &event)
00619 {
00620     wxDC &dc = event.GetDC();
00621 
00622     wxIFMComponent *component;
00623     wxRegionContain result;
00624 
00625     // don't paint a component if we don't have to
00626     const wxRegion &region = event.GetUpdateRegion();
00627     for( wxIFMComponentList::const_iterator i = m_containers.begin(), end = m_containers.end(); i != end; ++i )
00628     {
00629         component = *i;
00630 
00631         if( !component->IsVisible() )
00632             continue;
00633         else
00634         {
00635             result = region.Contains(component->m_rect);
00636             if( result == wxInRegion || result == wxPartRegion )
00637             {
00638                 // make a copy of the region and find the parts of the component
00639                 // that need updating
00640                 //wxRegion new_region = region;
00641                 //new_region.Intersect(component->m_rect);
00642                 component->Paint(dc, region);
00643             }
00644         }
00645     }
00646 }
00647 
00648 wxIFMComponent *wxIFMDefaultInterfacePlugin::GetComponentByPos(const wxPoint &pos, wxIFMComponent *component, bool floating)
00649 {
00650 #if IFM_CANFLOAT
00651     if( floating )
00652     {
00653         wxIFMComponent *component = GetFloatingComponentByPos(GetManager()->GetParent()->ClientToScreen(pos));
00654         if( component )
00655             return component;
00656     }
00657 #endif
00658 
00659     if( component == NULL )
00660     {
00661         wxIFMComponent *ret;
00662         for( wxIFMComponentList::const_iterator i = m_containers.begin(), end = m_containers.end(); i != end; ++i )
00663         {
00664             ret = GetComponentByPos(pos, *i);
00665             if( ret )
00666                 return ret;
00667         }
00668         return NULL;
00669     }
00670 
00671     //wxIFMHitTestEvent evt(component, IFM_COORDS_ABSOLUTE, pos);
00672     //ProcessPluginEvent(evt);
00673     if( !component->m_hidden && component->m_rect.Inside(pos) )
00674 
00675     //if( evt.GetPassed() )
00676     {
00677         // check children
00678         wxIFMComponent *ret;
00679         const wxIFMComponentArray &children = component->m_children;
00680         for( size_t i = 0; i < children.GetCount(); i++ )
00681         //for( wxIFMComponentArray::const_iterator i = children.begin(), end = children.end(); i != end; ++i )
00682         {
00683             ret = GetComponentByPos(pos, children[i]);
00684             if( ret )
00685                 return ret;
00686         }
00687         return component;
00688     }
00689 
00690     return NULL;
00691 }
00692 
00693 void wxIFMDefaultInterfacePlugin::OnGetContentRect(wxIFMRectEvent &event)
00694 {
00695     wxRect m_contentRect = GetManager()->GetInterfaceRect();
00696     wxIFMComponent *container;
00697     wxIFMContainerData *data;
00698 
00699     // update containers beginning from the start of the list
00700     for( wxIFMComponentList::const_iterator i = m_containers.begin(), end = m_containers.end(); i != end; ++i )
00701     {
00702         container = *i;
00703         data = IFM_GET_EXTENSION_DATA(container, wxIFMContainerData);
00704 
00705         wxIFMRectEvent rectevt(wxEVT_IFM_GETRECT, container);
00706         ProcessPluginEvent(rectevt);
00707         const wxRect &rect = rectevt.GetRect();
00708 
00709         switch(data->m_orientation)
00710         {
00711             // skip docked containers
00712             case IFM_ORIENTATION_DOCKED:
00713                 continue;
00714 
00715             case IFM_ORIENTATION_LEFT:
00716                 m_contentRect.width -= rect.width;
00717                 m_contentRect.x += rect.width;
00718                 break;
00719 
00720             case IFM_ORIENTATION_RIGHT:
00721                 m_contentRect.width -= rect.width;
00722                 break;
00723 
00724             case IFM_ORIENTATION_TOP:
00725                 m_contentRect.y += rect.height;
00726                 m_contentRect.height -= rect.height;
00727                 break;
00728 
00729             case IFM_ORIENTATION_BOTTOM:
00730                 m_contentRect.height -= rect.height;
00731                 break;
00732 
00733             default:
00734                 wxFAIL_MSG(wxT("Invalid orientation value"));
00735         }
00736     }
00737 
00738     // return content rect
00739     event.SetRect(m_contentRect);
00740 }
00741 
00742 #if IFM_CANFLOAT
00743 void wxIFMDefaultInterfacePlugin::OnCreateFloatingWindow(wxIFMCreateFloatingWindowEvent &event)
00744 {
00745     // component being floated
00746     wxIFMComponent *component = event.GetComponent();
00747 
00748     wxASSERT_MSG(component, wxT("Creating a floating window for a NULL component?"));
00749     if( !component )
00750         return;
00751 
00752     // create a frame to float with
00753     long style = IFM_FLOATING_FRAME_STYLE;
00754 
00755     wxIFMFloatingWindowBase *window = new wxIFMFloatingFrame(this, event.GetParent(), wxID_ANY, wxT(""),
00756         wxPoint(0,0), wxSize(0,0), style);
00757     event.SetWindow(window);
00758 
00759     // create the root component as well
00760     if( event.GetComponent()->GetType() == IFM_COMPONENT_CONTAINER )
00761         window->m_component = event.GetComponent();
00762     else
00763     {
00764         wxIFMNewComponentEvent evt(IFM_COMPONENT_FLOATING_ROOT);
00765         ProcessPluginEvent(evt);
00766         window->m_component = evt.GetComponent();
00767 
00768         wxASSERT_MSG(window->m_component, wxT("NULL floating root returned?"));
00769         if( !window->m_component )
00770             return;
00771     }
00772 
00773     // tell the root component its floating
00774     wxIFMFloatNotifyEvent fltevt(window->GetComponent(), true, window);
00775     ProcessPluginEvent(fltevt);
00776 
00777     // horizontal child alignment by default
00778     if( window->GetComponent()->m_alignment == IFM_ALIGN_NONE )
00779         window->GetComponent()->m_alignment = IFM_ALIGN_HORIZONTAL;
00780 
00781     wxIFMContainerData *contdata = IFM_GET_EXTENSION_DATA(window->m_component, wxIFMContainerData);
00782     if( contdata )
00783         contdata->m_orientation = IFM_ORIENTATION_FLOAT;
00784 
00785     // dock the component into the root component if needed
00786     if( component->GetType() != IFM_COMPONENT_CONTAINER )
00787     {
00788         wxIFMDockEvent dockevt(component, window->GetComponent(), 0);
00789         ProcessPluginEvent(dockevt);
00790     }
00791 }
00792 
00793 void wxIFMDefaultInterfacePlugin::OnDestroyFloatingWindow(wxIFMDestroyFloatingWindowEvent &event)
00794 {
00795     wxIFMFloatingWindowBase *base = event.GetWindow();
00796 
00797     wxASSERT_MSG(base, wxT("Destroying a NULL floating window?"));
00798     if( !base )
00799         return;
00800 
00801     // remove the floating window from the floating window array
00802     //for( int i = 0, count = m_floatingWindows.GetCount(); i < count; ++i )
00803     for( wxIFMFloatingWindowArray::iterator i = m_floatingWindows.begin(), end = m_floatingWindows.end(); i != end; ++i )
00804     {
00805         //if( m_floatingWindows[i] == base )
00806         if( *i == base )
00807         {
00808             //m_floatingWindows.RemoveAt(i);
00809             m_floatingWindows.erase(i);
00810             break;
00811         }
00812     }
00813 
00814     base->m_destroyRoot = event.ShouldDestroyRoot();
00815 
00816     delete base;
00817 }
00818 
00819 #endif
00820 
00821 /*
00822 wxIFMDefaultContainerPlugin implementation
00823 */
00824 BEGIN_EVENT_TABLE(wxIFMDefaultContainerPlugin, wxIFMExtensionPluginBase)
00825     EVT_IFM_NEWCOMPONENT    (wxIFMDefaultContainerPlugin::OnCreateComponent)
00826     EVT_IFM_DOCK            (wxIFMDefaultContainerPlugin::OnDock) // docks panel rows into the container
00827     EVT_IFM_UNDOCK          (wxIFMDefaultContainerPlugin::OnUndock)
00828     EVT_IFM_UPDATECOMPONENT (wxIFMDefaultContainerPlugin::OnUpdate)
00829     EVT_IFM_VISIBILITYCHANGED (wxIFMDefaultContainerPlugin::OnVisibilityChange)
00830     EVT_IFM_GETDESIREDSIZE  (wxIFMDefaultContainerPlugin::OnGetDesiredSize)
00831     EVT_IFM_SETDESIREDSIZE  (wxIFMDefaultContainerPlugin::OnSetDesiredSize)
00832     EVT_IFM_LEFTDOWN        (wxIFMDefaultContainerPlugin::OnLeftDown)
00833     EVT_IFM_PAINTDECOR      (wxIFMDefaultContainerPlugin::OnPaintDecor)
00834 
00835     EVT_IFM_COMPONENTBUTTONCLICK (wxIFMDefaultContainerPlugin::OnComponentButtonClick)
00836 
00837 #if IFM_CANFLOAT
00838     EVT_IFM_FLOATING_NOTIFY    (wxIFMDefaultContainerPlugin::OnFloatNotify)
00839 #endif
00840 END_EVENT_TABLE()
00841 
00842 wxIFMDefaultContainerPlugin::wxIFMDefaultContainerPlugin()
00843     : wxIFMExtensionPluginBase()
00844 { }
00845 
00846 bool wxIFMDefaultContainerPlugin::HasVisibleChildren(wxIFMComponent *component)
00847 {
00848     wxIFMComponentArray &children = component->m_children;
00849     wxIFMComponent *child;
00850 
00851     for( int i = 0, size = children.GetCount(); i < size; ++i )
00852     //for( wxIFMComponentArray::const_iterator i = children.begin(), end = children.end(); i != end; ++i )
00853     {
00854         child = children[i];
00855         //child = *i;
00856 
00857         // child containers alone don't count, but their children do
00858         if( child->GetType() == IFM_COMPONENT_CONTAINER )
00859         {
00860             if( HasVisibleChildren(child) )
00861                 return true;
00862         }
00863         else
00864         {
00865             if( child->IsVisible() )
00866                 return true;
00867         }
00868     }
00869 
00870     return false;
00871 }
00872 
00873 int wxIFMDefaultContainerPlugin::GetVisibleChildrenCount(wxIFMComponent *component)
00874 {
00875     wxIFMComponentArray &children = component->m_children;
00876     wxIFMComponent *child;
00877     int child_count = 0;
00878 
00879     for( int i = 0, size = children.GetCount(); i < size; ++i )
00880     //for( wxIFMComponentArray::const_iterator i = children.begin(), end = children.end(); i != end; ++i )
00881     {
00882         child = children[i];
00883         //child = *i;
00884 
00885         // child containers alone don't count, but their children do
00886         if( child->GetType() == IFM_COMPONENT_CONTAINER )
00887         {
00888             child_count += GetVisibleChildrenCount(child);
00889         }
00890         else
00891         {
00892             if( child->IsVisible() )
00893                 child_count++;
00894         }
00895     }
00896 
00897     return child_count;
00898 }
00899 
00900 bool wxIFMDefaultContainerPlugin::HasNonCloseableChildren(wxIFMComponent *component)
00901 {
00902     wxIFMComponentArray &children = component->m_children;
00903     wxIFMComponent *child;
00904 
00905     for( size_t i = 0; i < children.GetCount(); i++ )
00906     //for( wxIFMComponentArray::const_iterator i = children.begin(), end = children.end(); i != end; ++i )
00907     {
00908         child = children[i];
00909         //child = *i;
00910         if( !child->m_canHide )
00911             return true;
00912         else
00913             if( HasNonCloseableChildren(child) )
00914                 return true;
00915     }
00916 
00917     return false;
00918 }
00919 
00920 void wxIFMDefaultContainerPlugin::OnCreateComponent(wxIFMNewComponentEvent &event)
00921 {
00922     // only create containers or root floating components
00923     if( event.GetComponentType() == IFM_COMPONENT_CONTAINER ||
00924         event.GetComponentType() == IFM_COMPONENT_FLOATING_ROOT )
00925     {
00926         wxIFMComponent *container = new wxIFMComponent(GetIP(), IFM_COMPONENT_CONTAINER);
00927 
00928         // container specific storage
00929         wxIFMContainerData *data = new wxIFMContainerData(GetIP(), container);
00930 
00931         // add the drag gripper to the left side of all containers, and a close button
00932         data->m_tray_rect.width = IFM_CONTAINER_GRIPPER_WIDTH;
00933         container->m_margins.Set(0);
00934         container->m_margins.left = data->m_tray_rect.width;
00935         container->m_borders.Set(0);
00936 
00937 #if 0 // no button yet
00938         wxIFMComponentButton *btn;
00939         btn = data->m_buttonManager.AddButton(IFM_COMPONENT_ID_CLOSE);
00940         btn->m_bmp = &m_bmpClose;
00941         btn->m_bmpH = &m_bmpCloseH;
00942         btn->m_bmpP = &m_bmpCloseP;
00943 #endif
00944 
00945         container->AddExtensionData(data);
00946 
00947         // return the new component
00948         event.SetComponent(container);
00949     }
00950     else
00951         event.Skip();
00952 }
00953 
00954 // paint the drag gripper on the side of all containers
00955 void wxIFMDefaultContainerPlugin::OnPaintDecor(wxIFMPaintEvent &event)
00956 {
00957 #if IFM_CONTAINER_GRIPPER_WIDTH
00958     if( event.GetComponentType() == IFM_COMPONENT_CONTAINER )
00959     {
00960         wxIFMComponent *component = event.GetComponent();
00961 
00962         wxASSERT_MSG(component, wxT("NULL component?"));
00963         if( !component )
00964             return;
00965 
00966         wxIFMContainerData *data = IFM_GET_EXTENSION_DATA(component, wxIFMContainerData);
00967 
00968         wxASSERT_MSG(data, wxT("Container with no container data?"));
00969         if( !data )
00970             return;
00971 
00972         wxDC &dc = event.GetDC();
00973 
00975         wxBrush brush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW));
00976 
00977         dc.SetBrush(brush);
00978         dc.SetPen(*wxBLACK_PEN);
00979 
00980         dc.DrawRectangle(data->m_tray_rect);
00981     }
00982     else
00983 #endif
00984         event.Skip();
00985 }
00986 
00987 void wxIFMDefaultContainerPlugin::OnSetDesiredSize(wxIFMRectEvent &event)
00988 {
00989     if( event.GetComponentType() != IFM_COMPONENT_CONTAINER )
00990     {
00991         event.Skip();
00992         return;
00993     }
00994 
00995     GetNextHandler()->ProcessEvent(event);
00996 
00997     // set the desired size of our children
00998     wxIFMComponent *component = event.GetComponent();
00999 
01000     wxASSERT_MSG(component, wxT("NULL component?"));
01001     if( !component )
01002         return;
01003 
01004     const wxIFMComponentArray &children = component->m_children;
01005     wxRect rect, combined_rect;
01006     int numchildren = children.GetCount(), i;
01007     wxRect *child_rects = new wxRect[numchildren];
01008 
01009     // the desired size is specified in absolute cords, only use client coords for children
01010     wxIFMConvertRectEvent cvtevt(component, IFM_COORDS_ABSOLUTE, IFM_COORDS_CLIENT, event.GetRect());
01011     GetIP()->ProcessPluginEvent(cvtevt);
01012     rect = cvtevt.GetRect();
01013 
01014     // sum the total desired widths
01015     for( i = 0; i < numchildren; ++i )
01016     {
01017         wxIFMRectEvent evt(wxEVT_IFM_GETDESIREDSIZE, children[i]);
01018         GetIP()->ProcessPluginEvent(evt);
01019 
01020         child_rects[i] = evt.GetRect();
01021         combined_rect.height += child_rects[i].height;
01022         combined_rect.width += child_rects[i].width;
01023     }
01024 
01025     if( component->m_alignment == IFM_ALIGN_HORIZONTAL )
01026         combined_rect.height = rect.height;
01027     else if( component->m_alignment == IFM_ALIGN_VERTICAL )
01028         combined_rect.width = rect.width;
01029 
01030     for( i = 0; i < numchildren; ++i )
01031     {
01032         // scale desired size
01033         if( component->m_alignment == IFM_ALIGN_HORIZONTAL )
01034         {
01035             child_rects[i].height = combined_rect.height;
01036             child_rects[i].width = (int)(rect.width * ((double)child_rects[i].width / combined_rect.width));
01037         }
01038         else if( component->m_alignment == IFM_ALIGN_VERTICAL )
01039         {
01040             child_rects[i].width = combined_rect.width;
01041             child_rects[i].height = (int)(rect.height * ((double)child_rects[i].height / combined_rect.height));
01042         }
01043 
01044         wxIFMRectEvent evt(wxEVT_IFM_SETDESIREDSIZE, children[i], child_rects[i]);
01045         GetIP()->ProcessPluginEvent(evt);
01046     }
01047 
01048     delete[] child_rects;
01049 }
01050 
01051 void wxIFMDefaultContainerPlugin::OnGetDesiredSize(wxIFMRectEvent &event)
01052 {
01054 
01055     // only process containers
01056     if( event.GetComponentType() != IFM_COMPONENT_CONTAINER )
01057     {
01058         event.Skip();
01059         return;
01060     }
01061 
01062     // return the combined calculated size of all child components
01063     wxSize size;
01064     int width = 0, height = 0;
01065     wxIFMComponent *container = event.GetComponent();
01066 
01067     wxASSERT_MSG(container, wxT("NULL component?"));
01068     if( !container )
01069         return;
01070 
01071     // return 0 if hidden
01072     if( container->m_hidden  || !HasVisibleChildren(container) )
01073     {
01074         event.SetSize(wxSize(0,0));
01075         return;
01076     }
01077 
01078     for( int i = 0, count = container->m_children.GetCount(); i < count; ++i )
01079     //for( wxIFMComponentArray::const_iterator i = container->m_children.begin(), end = container->m_children.end(); i != end; ++i )
01080     {
01081         size = container->m_children[i]->GetDesiredSize();
01082         //size = (*i)->GetDesiredSize();
01083 
01084         if( container->m_alignment == IFM_ALIGN_HORIZONTAL )
01085         {
01086             if( size.GetHeight() > height )
01087                 height = size.GetHeight();
01088             width += size.GetWidth();
01089         }
01090         else if( container->m_alignment == IFM_ALIGN_VERTICAL )
01091         {
01092             if( size.GetWidth() > width )
01093                 width = size.GetWidth();
01094             height += size.GetHeight();
01095         }
01096     }
01097 
01098     size.Set(width, height);
01099 
01100     // never size less than our minimum
01101     wxSize min_size = container->GetMinSize();
01102     // convert the min size back into client coords
01103     min_size = container->GetConvertedRect(wxRect(wxPoint(), min_size), IFM_COORDS_ABSOLUTE, IFM_COORDS_CLIENT).GetSize();
01104 
01105     if( min_size.y > size.GetHeight() && min_size.y != IFM_NO_MINIMUM )
01106         size.SetHeight(min_size.y);
01107     if( min_size.x > size.GetWidth() && min_size.x != IFM_NO_MINIMUM  )
01108         size.SetWidth(min_size.x);
01109 
01110     // convert from client to absolute coords to allow containers to have border and margin widths
01111     event.SetSize(container->GetConvertedRect(wxRect(wxPoint(), size), IFM_COORDS_CLIENT, IFM_COORDS_ABSOLUTE).GetSize());
01112 }
01113 
01114 /*
01115 NOTE
01116 
01117   The event table entry for this function is commented out, because I no longer return (0,0,0,0)
01118   if it has no visible children
01119 */
01120 void wxIFMDefaultContainerPlugin::OnGetRect(wxIFMRectEvent &event)
01121 {
01122     if( event.GetComponentType() != IFM_COMPONENT_CONTAINER )
01123     {
01124         // return (0,0,0,0) if there are no visible children
01125         if( !HasVisibleChildren(event.GetComponent()) )
01126             event.SetRect(wxRect(0,0,0,0));
01127         else
01128             event.Skip();
01129     }
01130     else
01131         event.Skip();
01132 }
01133 
01134 void wxIFMDefaultContainerPlugin::OnDock(wxIFMDockEvent &event)
01135 {
01136     // handle docking of components into containers
01137     if( event.GetDestinationType() == IFM_COMPONENT_CONTAINER )
01138     {
01139         GetNextHandler()->ProcessEvent(event);
01140 
01141         wxIFMComponent *component = event.GetComponent();
01142 
01143         // if we are docking a container into a container, give the child container
01144         // the IFM_ORIENTATION_DOCKED orientation value
01145         // FIXME: should I do this?
01146         if( component->GetType() == IFM_COMPONENT_CONTAINER )
01147         {
01148             wxIFMContainerData *contdata = IFM_GET_EXTENSION_DATA(component, wxIFMContainerData);
01149 
01150             wxASSERT_MSG(contdata, wxT("Container with no container data?"));
01151             if( !contdata )
01152                 return;
01153 
01154             contdata->m_orientation = IFM_ORIENTATION_DOCKED;
01155         }
01156     }
01157     else
01158         event.Skip();
01159 }
01160 
01161 void wxIFMDefaultContainerPlugin::OnUndock(wxIFMUndockEvent &event)
01162 {
01163     if( event.GetParentType() == IFM_COMPONENT_CONTAINER && event.GetComponentType() == IFM_COMPONENT_PANEL )
01164     {
01165         /*
01166         If the container is a docked container and will only have one child docked into it
01167         after this event is processed:
01168 
01169         -undock the container
01170         -undock the child from the container
01171         -dock the child into the containers old parent,
01172         -and destroy the container
01173         */
01174         wxIFMComponent *container = event.GetParent();
01175         wxIFMComponent *parent = container->m_parent;
01176 
01177         if( container->m_docked && container->m_children.GetCount() == 2 )
01178         {
01179             // save the container's index for later
01180             int index = 0;
01181             {
01182                 wxIFMComponentArray &components = parent->m_children;
01183                 //for( int count = components.GetCount(); index < count; index++ )
01184                 for( wxIFMComponentArray::const_iterator i = components.begin(), end = components.end(); i != end; ++i, index++ )
01185                     if( *i /*components[index]*/ == container )
01186                         break;
01187             }
01188 
01189             GetNextHandler()->ProcessEvent(event);
01190             wxIFMComponent *child = container->m_children[0];
01191 
01192             // undock the child, but don't destroy the container
01193             wxIFMUndockEvent undockevt1(child, false);
01194             GetIP()->ProcessPluginEvent(undockevt1);
01195 
01196             // undock the container
01197             wxIFMUndockEvent undockevt2(container, false);
01198             GetIP()->ProcessPluginEvent(undockevt2);
01199 
01200             // dock the child where the container was
01201             wxIFMDockEvent dockevt(child, parent, index);
01202             GetIP()->ProcessPluginEvent(dockevt);
01203 
01204             // delete the container
01205             wxIFMDeleteComponentEvent delevt(container);
01206             GetIP()->ProcessPluginEvent(delevt);
01207 
01208             // reset the events parent because this function deletes it
01209             event.SetParent(parent);
01210             return;
01211         }
01212     }
01213 
01214     event.Skip();
01215 }
01216 
01217 #if IFM_CANFLOAT
01218 void wxIFMDefaultContainerPlugin::UpdateFloatingCaption(wxIFMComponent *container)
01219 {
01220     // if we are the root container of floating window and we have more than one child
01221     // display a native caption. If we have only one child, remove the native caption
01222     wxIFMFloatingData *floating_data = IFM_GET_EXTENSION_DATA(container, wxIFMFloatingData);
01223     if( !container->m_docked && floating_data->m_floating )
01224     {
01225         bool lower = false;
01226 
01227         wxWindow *wnd = floating_data->m_window->GetWindow();
01228         int style = wnd->GetWindowStyle();
01229 
01230         // hack around some wxWidgets "features"
01231         if( style & wxCAPTION )
01232             lower = true;
01233 
01234         if( GetVisibleChildrenCount(container) >= 2 )
01235         {
01236             if( style & wxCAPTION )
01237                 return;
01238             style |= (wxCAPTION | wxFRAME_TOOL_WINDOW);
01239         }
01240         else
01241         {
01242             if( !(style & wxCAPTION) )
01243                 return;
01244             style &= ~(wxCAPTION | wxFRAME_TOOL_WINDOW);
01245         }
01246 
01247         wnd->SetWindowStyle(style);
01248 
01249         // its not worth it, wxWidgets can fix their own bugs
01250         //if( lower )
01251             //wnd->Lower();
01252     }
01253 }
01254 #endif
01255 
01256 void wxIFMDefaultContainerPlugin::OnVisibilityChange(wxIFMComponentVisibilityChangedEvent &event)
01257 {
01258     if( event.GetComponentType() == IFM_COMPONENT_CONTAINER && !event.GetShow() )
01259     {
01260         wxIFMComponent *component = event.GetComponent();
01261         wxASSERT_MSG(component, wxT("NULL component?"));
01262         if( !component )
01263             return;
01264 
01265         // make sure our component buttons are hidden
01266         wxIFMContainerData *data = IFM_GET_EXTENSION_DATA(component, wxIFMContainerData);
01267         wxASSERT_MSG(data, wxT("Container with no container data?"));
01268         if( !data )
01269             return;
01270 
01271         //data->m_buttonManager.Show(false);
01272     }
01273 
01274     event.Skip();
01275 }
01276 
01277 void wxIFMDefaultContainerPlugin::OnShowComponent(wxIFMShowComponentEvent &event)
01278 {
01279     /*
01280     wxIFMComponent *component = event.GetComponent();
01281 
01282     wxASSERT_MSG(component, wxT("NULL component?"));
01283     if( !component )
01284         return;
01285 
01286     wxIFMComponent *parent = component->m_parent;
01287 
01288     // hide the container if it has no more visible children
01289     if( parent && parent->GetType() == IFM_COMPONENT_CONTAINER )
01290     {
01291 
01292     }
01293     */
01294 
01295     event.Skip();
01296 }
01297 
01298 void wxIFMDefaultContainerPlugin::OnUpdate(wxIFMUpdateComponentEvent &event)
01299 {
01300     // only process containers
01301     if( event.GetComponentType() != IFM_COMPONENT_CONTAINER )
01302     {
01303         event.Skip();
01304         return;
01305     }
01306 
01307     wxIFMComponent *container = event.GetComponent();
01308 
01309     wxASSERT_MSG(container, wxT("NULL component?"));
01310     if( !container )
01311         return;
01312 
01313     // size and position ourself first by passing the event down the chain
01314     // and to the default plugin
01315     GetNextHandler()->ProcessEvent(event);
01316 
01317     wxIFMContainerData *data = IFM_GET_EXTENSION_DATA(container, wxIFMContainerData);
01318 
01319     wxASSERT_MSG(data, wxT("Container with no container data?"));
01320     if( !data )
01321         return;
01322 
01323 #if IFM_CONTAINER_GRIPPER_WIDTH
01324     // update the size and position of the tray_rect
01325     wxRect bg_rect = container->GetBackgroundRect();
01326     data->m_tray_rect.height = bg_rect.height;
01327     data->m_tray_rect.x = bg_rect.x;
01328     data->m_tray_rect.y = bg_rect.y;
01329 #endif
01330 
01331 #if IFM_CANFLOAT
01332     // if we are hidden, make sure our floating frame is hidden (if applicable) and do nothing
01333     if( container->m_hidden )
01334     {
01335         wxIFMFloatingData *floating_data = IFM_GET_EXTENSION_DATA(container, wxIFMFloatingData);
01336         if( floating_data->m_floating && !container->m_docked )
01337         {
01338             if( floating_data->m_window->GetWindow()->IsShown() )
01339                 floating_data->m_window->GetWindow()->Hide();
01340         }
01341         return;
01342     }
01343 #endif
01344 
01345     // current will be -1 if no components are visible
01346     int current = wxIFMComponent::GetNextVisibleComponent(container->m_children, 0);
01347 
01348     if( !HasVisibleChildren(container) )
01349         current = -1;
01350 
01351 #if IFM_CANFLOAT
01352     wxIFMFloatingData *floating_data = IFM_GET_EXTENSION_DATA(container, wxIFMFloatingData);
01353     // if there are no visible children and we are a top level floating container, hide the floating window
01354     if( current == -1 && floating_data->m_floating && !container->m_docked )
01355     {
01356         floating_data->m_window->GetWindow()->Hide();
01357         return;
01358     }
01359 
01360     // if there are visible children and we are a top level floating container, make sure our floating window is shown
01361     if( current >= 0 && floating_data->m_floating && !container->m_docked )
01362     {
01363         if( !floating_data->m_window->GetWindow()->IsShown() )
01364             floating_data->m_window->GetWindow()->Show();
01365     }
01366 #endif
01367 
01368     // don't use this for now, its not done yet
01369 #if 0
01370     {
01371         wxIFMContainerData *data = IFM_GET_EXTENSION_DATA(container, wxIFMContainerData);
01372 
01373         wxASSERT_MSG(data, wxT("Container with no container data?"));
01374         if( !data )
01375             return;
01376 
01377         if( current == -1 )
01378         {
01379             // no visible children, make sure our component buttons are hidden too
01380             if( data )
01381                 data->m_buttonManager.Show(false);
01382 
01383             return;
01384         }
01385         else if( HasNonCloseableChildren(container) )
01386         {
01387             if( data )
01388             {
01389                 data->m_buttonManager.Show(true);
01390                 data->m_buttonManager.Show(false, IFM_COMPONENT_ID_CLOSE);
01391             }
01392         }
01393         else
01394             if( data )
01395                 data->m_buttonManager.Show(true);
01396     }
01397 #endif
01398 
01399     // calculate rects of our children using the calc rects event
01400     wxIFMCalcRectsEvent calcevt(container);
01401 
01402     wxIFMComponentArray &children = container->m_children;
01403     //wxIFMComponentArray::iterator i, end;
01404     //for( i = children.begin(), end = children.end(); i != end; ++i )
01405     for( size_t i1 = 0; i1 < children.GetCount(); i1++ )
01406         calcevt.AddComponent(children[i1]);
01407 
01408     GetIP()->ProcessPluginEvent(calcevt);
01409 
01410     // position children
01411     const wxRectArray &rects = calcevt.GetComponentRects();
01412     //wxRectArray::const_iterator ri;
01413     for( size_t i = 0, ri = 0; i < children.GetCount(); i++, ri++ )
01414     //for( i = children.begin(), end = children.end(), ri = rects.begin(); i != end; ++i, ri++ )
01415     {
01416         if( children[i]->m_hidden )
01417             continue;
01418         else
01419         {
01420             wxIFMUpdateComponentEvent updevt(children[i], rects[ri]);
01421             GetIP()->ProcessPluginEvent(updevt);
01422         }
01423     }
01424 
01425     // position our buttons
01426 #if 0
01427     wxIFMContainerData *data = IFM_GET_EXTENSION_DATA(container, wxIFMContainerData);
01428     wxASSERT_MSG(data, wxT("Container with no container data?"));
01429     if( data )
01430     {
01431         wxSize size = data->m_buttonManager.GetRect().GetSize();
01432         wxRect rect = container->GetBackgroundRect();
01433         data->m_buttonManager.SetPosition(wxPoint(rect.x + 1, rect.y));
01434         data->m_buttonManager.Layout();
01435     }
01436 #endif
01437 
01438 #if IFM_CANFLOAT
01439     // make sure our caption is hidden or shown as needed
01440     UpdateFloatingCaption(container);
01441 #endif
01442 }
01443 
01444 #if IFM_CANFLOAT
01445 void wxIFMDefaultContainerPlugin::OnFloatNotify(wxIFMFloatNotifyEvent &event)
01446 {
01447     if( event.GetComponentType() == IFM_COMPONENT_CONTAINER )
01448     {
01449         GetNextHandler()->ProcessEvent(event);
01450 
01451         wxIFMComponent *component = event.GetComponent();
01452 
01453         wxASSERT_MSG(component, wxT("NULL component?"));
01454         if( !component )
01455             return;
01456 
01457         wxIFMContainerData *data = IFM_GET_EXTENSION_DATA(component, wxIFMContainerData);
01458         wxASSERT_MSG(data, wxT("Container with no container data?"));
01459         if( !data )
01460             return;
01461 
01462         // if we are floating a top level floating container
01463         // remove ourselves from the top level container list first
01464         if( event.GetFloating() )
01465         {
01466             if( data && (data->m_orientation == IFM_ORIENTATION_LEFT || data->m_orientation == IFM_ORIENTATION_RIGHT || data->m_orientation == IFM_ORIENTATION_TOP || data->m_orientation == IFM_ORIENTATION_BOTTOM) )
01467             {
01468                 wxIFMRemoveTopContainerEvent evt(component);
01469                 GetIP()->ProcessPluginEvent(evt);
01470             }
01471         }
01472 
01473         //data->m_buttonManager.SetParent(component->GetParentWindow());
01474     }
01475     else
01476         event.Skip();
01477 }
01478 #endif
01479 
01480 void wxIFMDefaultContainerPlugin::OnComponentButtonClick(wxIFMComponentButtonEvent &event)
01481 {
01482     wxIFMComponent *component = event.GetComponent();
01483     if( component->GetType() == IFM_COMPONENT_CONTAINER )
01484     {
01485         wxIFMComponentButton *button = event.GetButton();
01486         if( button->GetID() == IFM_COMPONENT_ID_CLOSE )
01487         {
01488             // hide ourself
01489             component->Show(false, true);
01490             return;
01491         }
01492     }
01493 
01494     event.Skip();
01495 }
01496 
01497 void wxIFMDefaultContainerPlugin::OnLeftDown(wxIFMMouseEvent &event)
01498 {
01499     if( event.GetComponentType() == IFM_COMPONENT_CONTAINER )
01500     {
01501         wxPoint pos = event.GetMouseEvent().GetPosition();
01502 
01503         wxIFMComponent *component = event.GetComponent();
01504 
01505         wxASSERT_MSG(component, wxT("NULL component?"));
01506         if( !component )
01507             return;
01508 
01509         wxIFMContainerData *data = IFM_GET_EXTENSION_DATA(component, wxIFMContainerData);
01510 
01511         wxASSERT_MSG(data, wxT("Container with no container data?"));
01512         if( !data )
01513             return;
01514 
01515         if( data->m_tray_rect.Inside(pos) )
01516         {
01517             wxIFMInitDragEvent evt(component, component, pos);
01518             GetIP()->ProcessPluginEvent(evt);
01519         }
01520     }
01521     else
01522         event.Skip();
01523 }
01524 
01525 /*
01526 wxIFMDefaultPanelPlugin implementation
01527 */
01528 BEGIN_EVENT_TABLE(wxIFMDefaultPanelPlugin, wxIFMExtensionPluginBase)
01529     EVT_IFM_NEWCOMPONENT    (wxIFMDefaultPanelPlugin::OnCreateComponent)
01530     EVT_IFM_DELETECOMPONENT (wxIFMDefaultPanelPlugin::OnDestroyComponent)
01531     EVT_IFM_UPDATECOMPONENT (wxIFMDefaultPanelPlugin::OnUpdate)
01532     EVT_IFM_VISIBILITYCHANGED (wxIFMDefaultPanelPlugin::OnVisibilityChanged)
01533     EVT_IFM_SETCHILD        (wxIFMDefaultPanelPlugin::OnSetChild)
01534     EVT_IFM_SHOWCOMPONENT   (wxIFMDefaultPanelPlugin::OnShowComponent)
01535     EVT_IFM_PAINTDECOR      (wxIFMDefaultPanelPlugin::OnPaintDecor)
01536     EVT_IFM_PAINTBG         (wxIFMDefaultPanelPlugin::OnPaintBg)
01537     EVT_IFM_DOCK            (wxIFMDefaultPanelPlugin::OnDock)
01538     EVT_IFM_UNDOCK          (wxIFMDefaultPanelPlugin::OnUndock)
01539     EVT_IFM_COMPONENTBUTTONCLICK (wxIFMDefaultPanelPlugin::OnComponentButtonClick)
01540     EVT_IFM_LEFTDOWN       (wxIFMDefaultPanelPlugin::OnLeftDown)
01541     EVT_IFM_SELECTTAB       (wxIFMDefaultPanelPlugin::OnSelectTab)
01542     EVT_IFM_GETDESIREDSIZE  (wxIFMDefaultPanelPlugin::OnGetDesiredSize)
01543     EVT_IFM_SETDESIREDSIZE  (wxIFMDefaultPanelPlugin::OnSetDesiredSize)
01544     EVT_IFM_GETMINSIZE      (wxIFMDefaultPanelPlugin::OnGetMinSize)
01545     EVT_IFM_GETMAXSIZE      (wxIFMDefaultPanelPlugin::OnGetMaxSize)
01546     EVT_IFM_QUERYCHILD      (wxIFMDefaultPanelPlugin::OnQueryChild)
01547 
01548 #if IFM_CANFLOAT
01549     EVT_IFM_FLOATING_NOTIFY (wxIFMDefaultPanelPlugin::OnFloatNotify)
01550 #endif
01551 END_EVENT_TABLE()
01552 
01553 bool wxIFMDefaultPanelPlugin::Initialize(wxIFMInterfacePluginBase *plugin)
01554 {
01555     wxIFMExtensionPluginBase::Initialize(plugin);
01556 
01557     // load component button bitmaps
01558     m_bmpClose = wxBitmap(btn_hide_xpm);
01559     m_bmpMin = wxBitmap(btn_min_xpm);
01560     m_bmpMax = wxBitmap(btn_max_xpm);
01561     m_bmpCloseH = wxBitmap(btn_hide_h_xpm);
01562     m_bmpMinH = wxBitmap(btn_min_h_xpm);
01563     m_bmpMaxH = wxBitmap(btn_max_h_xpm);
01564     m_bmpCloseP = wxBitmap(btn_hide_hp_xpm);
01565     m_bmpMinP = wxBitmap(btn_min_hp_xpm);
01566     m_bmpMaxP = wxBitmap(btn_max_hp_xpm);
01567 
01568     // determine the height of the caption and tabs based on the height of its font
01569     m_caption_config.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
01570     m_caption_config.color = /*wxColour(0, 51, 153)*/ wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION);
01571 
01572     int w, h;
01573     GetManager()->GetParent()->GetTextExtent(_T(" "), &w, &h, 0, 0, &m_caption_config.font);
01574 
01575     m_caption_config.font_height = h;
01576     m_caption_config.padding = m_caption_config.font_height / 4;
01577     m_caption_config.height = m_caption_config.font_height + m_caption_config.padding;
01578 
01579     // configure tab data
01580     m_tab_config.font = m_caption_config.font;
01581     m_tab_config.font_color = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT);
01582     m_tab_config.font_height = h;
01583     m_tab_config.tab_padding = m_tab_config.font_height / 4;
01584     m_tab_config.tab_height = m_tab_config.font_height + m_tab_config.tab_padding * 2;
01585     m_tab_config.row_height = m_tab_config.tab_height + 2;
01586     m_tab_config.row_indent = 2;
01587     m_tab_config.rounding_factor = 3;
01588     m_tab_config.tab_spacing = -1;
01589 
01590     m_tab_config.tab_border_p = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW));
01591     m_tab_config.tab_active_bg_b = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNHIGHLIGHT));
01592     m_tab_config.tab_active_bg_p = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNHIGHLIGHT));
01593     m_tab_config.tab_inactive_bg_b = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
01594     m_tab_config.tab_inactive_bg_p = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
01595     m_tab_config.bg_brush = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT));
01596     m_tab_config.bg_pen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT));
01597     m_tab_config.line_pen = m_tab_config.tab_border_p;
01598 
01599     return true;
01600 }
01601 
01602 void wxIFMDefaultPanelPlugin::OnCreateComponent(wxIFMNewComponentEvent &event)
01603 {
01604     // create tabs
01605     if( event.GetComponentType() == IFM_COMPONENT_PANEL_TAB )
01606     {
01607         // create a new component
01608         wxIFMComponent *tab = new wxIFMComponent(GetIP(), IFM_COMPONENT_PANEL_TAB);
01609 
01610         // add panel specific data storage
01611         wxIFMPanelTabData *tabdata = new wxIFMPanelTabData();
01612 
01613         tab->AddExtensionData(tabdata);
01614 
01615         tab->m_borders.Set(0);
01616         tab->m_margins.Set(0);
01617 
01618         // return the new component
01619         event.SetComponent(tab);
01620     }
01621     // create panels too
01622     else if( event.GetComponentType() == IFM_COMPONENT_PANEL )
01623     {
01624         wxIFMComponent *panel = new wxIFMComponent(GetIP(), IFM_COMPONENT_PANEL);
01625         wxIFMPanelData *data = new wxIFMPanelData(GetIP(), panel);
01626         panel->AddExtensionData(data);
01627 
01628         panel->m_margins.Set(1);
01629         panel->m_margins.top += m_caption_config.height + IFM_CAPTION_PAD*2;
01630         panel->m_margins.bottom += m_tab_config.row_height;
01631         panel->m_borders.Set(1);
01632 
01633         // add close, maximize, minimize buttons
01634         wxIFMComponentButton *btn;
01635 
01636         /*
01637             We dont use these buttons yet, comment them out until they are implemented
01638 
01639         btn = data->m_buttonManager.AddButton(IFM_COMPONENT_ID_MINIMIZE);
01640         btn->m_bmp = &m_bmpMin;
01641         btn->m_bmpH = &m_bmpMinH;
01642         btn->m_bmpP = &m_bmpMinP;
01643 
01644         btn = data->m_buttonManager.AddButton(IFM_COMPONENT_ID_MAXIMIZE);
01645         btn->m_bmp = &m_bmpMax;
01646         btn->m_bmpH = &m_bmpMaxH;
01647         btn->m_bmpP = &m_bmpMaxP;
01648         */
01649 
01650         data->m_button_manager.SetPosition(wxPoint(1, (m_caption_config.height - IFM_COMPONENT_BUTTON_Y) / 2));
01651         btn = data->m_button_manager.AddButton(IFM_COMPONENT_ID_CLOSE);
01652         btn->m_bmp = &m_bmpClose;
01653         btn->m_bmpH = &m_bmpCloseH;
01654         btn->m_bmpP = &m_bmpCloseP;
01655         btn->SetBackgroundColour(m_caption_config.color);
01656 
01657         event.SetComponent(panel);
01658     }
01659     else
01660         event.Skip();
01661 }
01662 
01663 void wxIFMDefaultPanelPlugin::OnDestroyComponent(wxIFMDeleteComponentEvent &event)
01664 {
01665     if( event.GetComponentType() == IFM_COMPONENT_PANEL )
01666     {
01667         wxIFMComponent *panel = event.GetComponent();
01668 
01669         wxASSERT_MSG(panel, wxT("NULL component?"));
01670         if( !panel )
01671             return;
01672 
01673         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(panel, wxIFMPanelData);
01674 
01675         wxASSERT_MSG(data, wxT("Panel with no panel data?"));
01676         if( !data )
01677             return;
01678 
01679         data->m_button_manager.Hide();
01680     }
01681     event.Skip();
01682 }
01683 
01685 void wxIFMDefaultPanelPlugin::OnSetChild(wxIFMSetChildEvent &event)
01686 {
01687     wxIFMComponent *panel = event.GetComponent();
01688 
01689     // set the child
01690     panel->m_child = event.GetChild();
01691     panel->m_childType = event.GetChildType();
01692 
01693     // hide the child if the panel is hidden
01694     if( panel->m_hidden )
01695         panel->m_child->Hide();
01696 
01697     /*
01698     wxIFMPanelTabData *data = IFM_GET_EXTENSION_DATA(panel, wxIFMPanelTabData);
01699 
01700     // give us a caption if needed
01701     if( panel->m_childType == IFM_CHILD_TOOLBAR )
01702     {
01703         data->m_hasCaption = false;
01704         data->m_buttonManager.Hide();
01705 
01706         // set max and min heights to match toolbar height
01707         panel->m_minSize = panel->m_child->GetBestSize();
01708         panel->m_maxSize = panel->m_child->GetBestSize();
01709         panel->m_desiredSize = panel->m_child->GetBestSize();
01710     }
01711     else
01712     {
01713         data->m_buttonManager.Show();
01714         data->m_hasCaption = true;
01715         panel->m_margins.top += m_caption_config.height + 1;
01716     }
01717 
01718     data->m_buttonManager.Show(panel->m_canHide, IFM_COMPONENT_ID_CLOSE);
01719     */
01720 }
01721 
01722 void wxIFMDefaultPanelPlugin::OnQueryChild(wxIFMQueryChildEvent &event)
01723 {
01724     wxIFMComponent *tab = event.GetComponent();
01725     if( tab->GetType() == IFM_COMPONENT_PANEL_TAB )
01726     {
01727         event.SetVisible(false);
01728         wxIFMComponent *parent = tab->m_parent;
01729 
01730         if( !parent->IsVisible() )
01731             return;
01732 
01733         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(parent, wxIFMPanelData);
01734         for(int i = 0; i < data->m_tabs.GetCount(); i++)
01735         {
01736             wxIFMTab *tab = data->m_tabs[i];
01737             if(tab->m_tab->m_child == event.GetChild())
01738             {
01739                 event.SetVisible(tab->m_visible);
01740                 break;
01741             }
01742         }
01743     }
01744     else
01745         event.Skip();
01746 }
01747 
01748 void wxIFMDefaultPanelPlugin::OnDock(wxIFMDockEvent &event)
01749 {
01750     // if we are docking a panel with one tab, dock the tab, instead of the panel
01751     if( event.GetDestinationType() == IFM_COMPONENT_PANEL && event.GetComponentType() == IFM_COMPONENT_PANEL )
01752     {
01753         wxIFMComponent *panel = event.GetComponent();
01754 
01755         wxASSERT_MSG(panel, wxT("NULL component?"));
01756         if( !panel )
01757             return;
01758 
01759         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(panel, wxIFMPanelData);
01760 
01761         wxASSERT_MSG(data, wxT("Panel with no panel data?"));
01762         if( !data )
01763             return;
01764 
01765         if( data->m_tabs.size() == 1 )
01766         {
01767             wxIFMComponent *tab = data->m_tabs[0]->m_tab;
01768             // dock the tab of that panel into the destination panel
01769             wxIFMUndockEvent undock(tab, false);
01770             GetIP()->ProcessPluginEvent(undock);
01771 
01772             wxIFMDockEvent dock(tab, event.GetDestination(), event.GetIndex());
01773             GetIP()->ProcessPluginEvent(dock);
01774             return;
01775         }
01776     }
01777 
01778     // dock stuff into panels
01779     if( event.GetDestinationType() == IFM_COMPONENT_PANEL )
01780     {
01781         // default processing
01782         GetNextHandler()->ProcessEvent(event);
01783 
01784         wxIFMComponent *tabbed_panel = event.GetDestination();
01785         wxIFMComponent *panel_tab = event.GetComponent();
01786 
01787         wxASSERT_MSG(tabbed_panel && panel_tab, wxT("NULL tab or panel?"));
01788         if( !tabbed_panel || !panel_tab )
01789             return;
01790 
01791         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(tabbed_panel, wxIFMPanelData);
01792 
01793         wxASSERT_MSG(data, wxT("Panel with no panel data?"));
01794         if( !data )
01795             return;
01796 
01797         // if this is the first tab of this panel, make the panels desired size large enough
01798         // to accomodate the panel
01799         if( tabbed_panel->m_children.size() == 1 )
01800         {
01801             tabbed_panel->SetDesiredSize(tabbed_panel->GetConvertedRect( // convert from client to absolute
01802                 wxRect(wxPoint(), panel_tab->GetDesiredSize()), // make a rect
01803                 IFM_COORDS_CLIENT, IFM_COORDS_ABSOLUTE).GetSize()); // get its size
01804         }
01805 
01806         int index = event.GetIndex(), count = panel_tab->m_children.size() - 1;
01807 
01808         // create and initialize the tab
01809         wxIFMTab *tab = new wxIFMTab;
01810         tab->m_tab = panel_tab;
01811 
01812         // calculate the width of the tabs name string
01813         int h;
01814         GetManager()->GetParent()->GetTextExtent(tab->m_tab->m_name, &tab->m_name_width, &h, 0, 0, &m_tab_config.font);
01815         if( tab->m_name_width == 0 )
01816             tab->m_name_width = 20;
01817 
01818         if( index == IFM_DEFAULT_INDEX || index > count )
01819         {
01820             // add it as the last tab
01821             data->m_tabs.push_back(tab);
01822         }
01823         else
01824         {
01825             // add it where it wants to be
01826             data->m_tabs.insert(data->m_tabs.begin() + index, tab);
01827         }
01828 
01829         panel_tab->m_parent = tabbed_panel;
01830 
01831         wxIFMSelectTabEvent evt(tabbed_panel, tab, false);
01832         GetIP()->ProcessPluginEvent(evt);
01833     }
01834     // also, if a tab is docked directly into a container
01835     // dock a panel there instead, and then dock the tab into the panel
01836     else if( event.GetDestinationType() == IFM_COMPONENT_CONTAINER && event.GetComponentType() == IFM_COMPONENT_PANEL_TAB )
01837     {
01838         wxIFMComponent *tab = event.GetComponent();
01839 
01840         // create the tab
01841         wxIFMNewComponentEvent newevt(IFM_COMPONENT_PANEL);
01842         GetIP()->ProcessPluginEvent(newevt);
01843 
01844         wxIFMComponent *panel = newevt.GetComponent();
01845 
01846         // dock the panel where the tab was going
01847         wxIFMDockEvent dockevt1(panel, event.GetDestination(), event.GetIndex());
01848         GetIP()->ProcessPluginEvent(dockevt1);
01849 
01850         // dock the tab into the panel
01851         wxIFMDockEvent dockevt2(tab, panel, 0);
01852         GetIP()->ProcessPluginEvent(dockevt2);
01853     }
01854     else
01855         event.Skip();
01856 }
01857 
01858 void wxIFMDefaultPanelPlugin::OnUndock(wxIFMUndockEvent &event)
01859 {
01860     // undock stuff from panels
01861     if( event.GetParentType() == IFM_COMPONENT_PANEL )
01862     {
01863         // find the tab which represented this component and remove it
01864 
01865         wxIFMComponent *panel = event.GetParent();
01866         wxIFMComponent *panel_tab = event.GetComponent();
01867 
01868         wxASSERT_MSG(panel, wxT("NULL component?"));
01869         if( !panel )
01870             return;
01871 
01872         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(panel, wxIFMPanelData);
01873 
01874         wxASSERT_MSG(data, wxT("Tabbed panel with no tabbed panel data?"));
01875         if( !data )
01876             return;
01877 
01878         wxIFMTab *tab = NULL;
01879         for( size_t i = 0; i < data->m_tabs.GetCount(); i++ )
01880         //for( wxIFMTabArray::iterator i = data->m_tabs.begin(), end = data->m_tabs.end(); i != end; ++i )
01881         {
01882             tab = data->m_tabs[i];
01883             if( tab->m_tab == panel_tab )
01884             {
01885                 data->m_tabs.RemoveAt(i);
01886                 break;
01887             }
01888             tab = NULL;
01889         }
01890 
01891         // select a new tab
01892         if( data->m_tabs.size() > 0 )
01893         {
01894             if( tab == data->m_active_tab )
01895             {
01896                 wxIFMSelectTabEvent evt(panel, data->m_tabs[0], true);
01897                 GetIP()->ProcessPluginEvent(evt);
01898             }
01899         }
01900         else
01901             data->m_active_tab = NULL;
01902 
01903         delete tab;
01904 
01905         // default processing
01906         GetNextHandler()->ProcessEvent(event);
01907     }
01908     else
01909         event.Skip();
01910 }
01911 
01912 void wxIFMDefaultPanelPlugin::OnUpdate(wxIFMUpdateComponentEvent &event)
01913 {
01914     // process tabs
01915     if( event.GetComponentType() == IFM_COMPONENT_PANEL_TAB )
01916     {
01917         wxIFMComponent *tab = event.GetComponent();
01918 
01919         wxASSERT_MSG(tab, wxT("NULL component?"));
01920         if( !tab )
01921             return;
01922 
01923         wxASSERT_MSG(tab->m_child, wxT("Panel with null child!"));
01924         if( !tab->m_child )
01925             return;
01926 
01927         if( !tab->IsVisible() )
01928         {
01929             // make sure our child is hidden
01930             if( tab->m_child->IsShown() )
01931                 tab->m_child->Show(false);
01932             return;
01933         }
01934         else
01935         {
01936             // make sure our child is visible since the tab is visible
01937             if( !tab->m_child->IsShown() )
01938                 tab->m_child->Show();
01939         }
01940 
01941         // size and position ourself by passing the event down the chain
01942         // and to the default component handler
01943         // WARNING: If plugins are added in the wrong order GetNextHandler may return null!
01944         GetNextHandler()->ProcessEvent(event);
01945 
01946         // request client size and position
01947         wxIFMRectEvent rectevt2(wxEVT_IFM_GETCLIENTRECT, tab);
01948         GetIP()->ProcessPluginEvent(rectevt2);
01949 
01950         // size our child window
01951         tab->m_child->SetSize(rectevt2.GetRect());
01952     }
01953     // and panels
01954     else if( event.GetComponentType() == IFM_COMPONENT_PANEL )
01955     {
01956         wxIFMComponent *panel = event.GetComponent();
01957 
01958         wxASSERT_MSG(panel, wxT("NULL component?"));
01959         if( !panel )
01960             return;
01961 
01962         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(panel, wxIFMPanelData);
01963 
01964         wxASSERT_MSG(data, wxT("Tabbed panel with no tabbed panel data?"));
01965         if( !data )
01966             return;
01967 
01968         if( !data->m_active_tab )
01969             return;
01970 
01971         // forward the update event to the active panel but size ourself first
01972         GetNextHandler()->ProcessEvent(event);
01973 
01974         // set the caption rect
01975         wxRect rect = panel->GetBackgroundRect();
01976         data->m_caption.x = rect.x + IFM_CAPTION_PAD;
01977         data->m_caption.y = rect.y + IFM_CAPTION_PAD;
01978         data->m_caption.height = m_caption_config.height;
01979         data->m_caption.width = rect.width - IFM_CAPTION_PAD*2;
01980 
01981         // set the caption title position too
01982         data->m_titlePos.x = data->m_caption.x + m_caption_config.padding;
01983         data->m_titlePos.y = data->m_caption.y + (m_caption_config.height - m_caption_config.font_height)/2;
01984 
01985         // update the active panel tab
01986         wxRect client_rect = panel->GetClientRect();
01987         wxIFMUpdateComponentEvent evt(data->m_active_tab->m_tab, client_rect);
01988         GetIP()->ProcessPluginEvent(evt);
01989 
01990         wxRect tab_rect;
01991         tab_rect.x = rect.x + m_tab_config.row_indent;
01992         tab_rect.y = rect.y + rect.height - m_tab_config.row_height;
01993         tab_rect.height = m_tab_config.tab_height;
01994 
01995         // update the tab positions
01996         for( size_t i = 0; i < data->m_tabs.GetCount(); i++ )
01997         //for( wxIFMTabArray::iterator i = data->m_tabs.begin(), end = data->m_tabs.end(); i != end; ++i )
01998         {
01999             wxIFMTab *tab = data->m_tabs[i];
02000 
02001             if( !tab->m_visible )
02002                 continue;
02003 
02004             wxIFMPanelTabData *tab_data = IFM_GET_EXTENSION_DATA(tab->m_tab, wxIFMPanelTabData);
02005 
02006             tab_rect.width = tab->m_name_width + m_tab_config.tab_padding + m_tab_config.tab_padding;
02007 
02008             if(tab_data && tab_data->m_bitmap.Ok())
02009                 tab_rect.width += tab_data->m_bitmap.GetWidth() + m_tab_config.tab_padding;
02010 
02011             tab->m_rect = tab_rect;
02012             tab_rect.x += tab_rect.width + m_tab_config.tab_spacing;
02013         }
02014 
02015         // position compontent buttons
02016         wxSize size = data->m_button_manager.GetRect().GetSize();
02017         data->m_button_manager.SetPosition(wxPoint(data->m_caption.x + data->m_caption.width - size.x, data->m_caption.y));
02018         data->m_button_manager.Layout();
02019     }
02020     else
02021         event.Skip();
02022 }
02023 
02024 void wxIFMDefaultPanelPlugin::OnShowComponent(wxIFMShowComponentEvent &event)
02025 {
02026     GetNextHandler()->ProcessEvent(event);
02027 
02028     bool show = event.GetShow();
02029 
02030     wxIFMComponent *component = event.GetComponent();
02031 
02032     wxASSERT_MSG(component, wxT("NULL component?"));
02033     if( !component )
02034         return;
02035 
02036     wxIFMComponent *panel = component->m_parent;
02037 
02038     if( !panel )
02039         return;
02040 
02041     if( panel->GetType() == IFM_COMPONENT_PANEL )
02042     {
02043         // show or hide the tab for this child
02044         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(panel, wxIFMPanelData);
02045 
02046         // don't do anything if we hide this component ourselves
02047         if( data->m_dont_hide_tab )
02048         {
02049             data->m_dont_hide_tab = false;
02050             return;
02051         }
02052 
02053         // find the tab
02054         wxIFMTab *tab = NULL;
02055         for( size_t i = 0; i < data->m_tabs.GetCount(); i++ )
02056         //for( wxIFMTabArray::iterator i = data->m_tabs.begin(), end = data->m_tabs.end(); i != end; ++i )
02057         {
02058             tab = data->m_tabs[i];
02059             if( tab->m_tab == component )
02060                 break;
02061         }
02062 
02063         tab->m_visible = show;
02064 
02065         if( !show )
02066         {
02067             bool vis = false;
02068 
02069             // if there are no visible tabs left, hide the panel too
02070             for( size_t i = 0; i < data->m_tabs.GetCount(); i++ )
02071             //for( wxIFMTabArray::iterator i = data->m_tabs.begin(), end = data->m_tabs.end(); i != end; ++i )
02072             {
02073                 wxIFMTab *tab = data->m_tabs[i];
02074                 if( tab->m_visible )
02075                 {
02076                     vis = true;
02077                     break;
02078                 }
02079             }
02080 
02081             if( !vis )
02082                 panel->Hide();
02083 
02084             // if we hide the active tab, select another
02085             else if( tab->m_active )
02086             {
02087                 // find the next visible tab to select
02088                 wxIFMTab *new_tab;
02089                 for( size_t i = 0; i < data->m_tabs.GetCount(); i++ )
02090                 //for( wxIFMTabArray::iterator i = data->m_tabs.begin(), end = data->m_tabs.end(); i != end; ++i )
02091                 {
02092                     new_tab = data->m_tabs[i];
02093                     if( new_tab->m_visible && new_tab != tab )
02094                     {
02095                         wxIFMSelectTabEvent evt(panel, new_tab, false);
02096                         GetIP()->ProcessPluginEvent(evt);
02097                         break;
02098                     }
02099                 }
02100             }
02101         }
02102         // select the tab if its being shown
02103         else
02104         {
02105             wxIFMSelectTabEvent evt(panel, tab, false);
02106             GetIP()->ProcessPluginEvent(evt);
02107         }
02108     }
02109 }
02110 
02111 void wxIFMDefaultPanelPlugin::OnVisibilityChanged(wxIFMComponentVisibilityChangedEvent &event)
02112 {
02113     wxIFMComponent *component = event.GetComponent();
02114 
02115     wxASSERT_MSG(component, wxT("NULL component?"));
02116     if( !component )
02117         return;
02118 
02119     bool shown = event.GetShow();
02120 
02121     if( event.GetComponentType() == IFM_COMPONENT_PANEL_TAB )
02122     {
02123         // we would normally show the child here as well, but we
02124         // will wait for the next update component event and let it
02125         // take care of that for us
02126 
02127         // we will however hide the child immediately if needed
02128         if( !shown )
02129             component->m_child->Show(false);
02130     }
02131     else if( event.GetComponentType() == IFM_COMPONENT_PANEL )
02132     {
02133         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(component, wxIFMPanelData);
02134 
02135         wxASSERT_MSG(data, wxT("Tabbed panel with no tabbed panel data?"));
02136         if( !data )
02137             return;
02138 
02139         data->m_button_manager.Show(shown);
02140     }
02141 
02142     // if the component's parent is a panel, then the component is a tab of that panel.
02143     // show or hide that tab if the component was hidden
02144 
02145     // skip to let the default implementation send the notification to our children, in case we have any
02146     event.Skip();
02147 }
02148 
02149 #if IFM_CANFLOAT
02150 
02151 void wxIFMDefaultPanelPlugin::OnFloatNotify(wxIFMFloatNotifyEvent &event)
02152 {
02153     wxIFMComponent *component = event.GetComponent();
02154 
02155     wxASSERT_MSG(component, wxT("NULL component?"));
02156     if( !component )
02157         return;
02158 
02159     // process for panel tabs
02160     if( event.GetComponentType() == IFM_COMPONENT_PANEL_TAB )
02161     {
02162         // let the default plugin go first
02163         GetNextHandler()->ProcessEvent(event);
02164 
02165         if( component->m_child )
02166             component->m_child->Reparent(component->GetParentWindow());
02167     }
02168     // and panels
02169     else if( event.GetComponentType() == IFM_COMPONENT_PANEL )
02170     {
02171         // let the default plugin go first
02172         GetNextHandler()->ProcessEvent(event);
02173 
02174         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(component, wxIFMPanelData);
02175 
02176         wxASSERT_MSG(data, wxT("Panel with no panel data?"));
02177         if( !data )
02178             return;
02179 
02180         data->m_button_manager.SetParent(component->GetParentWindow());
02181     }
02182     else
02183         event.Skip();
02184 }
02185 
02186 #endif // IFM_CANFLOAT
02187 
02188 void wxIFMDefaultPanelPlugin::OnPaintDecor(wxIFMPaintEvent &event)
02189 {
02190     if( event.GetComponentType() == IFM_COMPONENT_PANEL )
02191     {
02192         wxRegion region = event.GetRegion();
02193         wxIFMComponent *component = event.GetComponent();
02194 
02195         wxASSERT_MSG(component, wxT("NULL component?"));
02196         if( !component )
02197             return;
02198 
02199         if( component->m_hidden )
02200             return;
02201 
02202         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(component, wxIFMPanelData);
02203 
02204         wxASSERT_MSG(data, wxT("Panel with no panel data?"));
02205         if( !data )
02206             return;
02207 
02208         wxDC &dc = event.GetDC();
02209         wxRegionContain result = region.Contains(data->m_caption);
02210         if( result == wxPartRegion || result == wxInRegion )
02211         {
02212             dc.SetBrush(wxBrush(m_caption_config.color));
02213             dc.SetPen(wxPen(m_caption_config.color));
02214 
02215             // draw caption background
02216             dc.DrawRectangle(data->m_caption);
02217 
02218             // draw caption text
02219             dc.SetFont(m_caption_config.font);
02220             dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_CAPTIONTEXT));
02221             if( data->m_active_tab )
02222                 dc.DrawText(data->m_active_tab->m_tab->m_name, data->m_titlePos.x, data->m_titlePos.y);
02223         }
02224 
02225         // draw the tabs
02226         DrawTabs(dc, component, region, data->m_tabs);
02227     }
02228     else
02229         event.Skip();
02230 }
02231 
02232 void wxIFMDefaultPanelPlugin::OnPaintBg(wxIFMPaintEvent &event)
02233 {
02234     if( event.GetComponentType() == IFM_COMPONENT_PANEL || event.GetComponentType() == IFM_COMPONENT_PANEL_TAB )
02235     {
02236         wxIFMComponent *component = event.GetComponent();
02237 
02238         wxASSERT_MSG(component, wxT("NULL component?"));
02239         if( !component )
02240             return;
02241 
02242         if( component->m_hidden )
02243             return;
02244 
02245         wxRect rect = component->GetBackgroundRect();
02246         wxDC &dc = event.GetDC();
02247 
02248         // draw the background with the same color as the active tab background
02249         dc.SetBrush(m_tab_config.tab_active_bg_b);
02250         dc.SetPen(wxPen(m_tab_config.tab_active_bg_b.GetColour()));
02251 
02252         dc.DrawRectangle(rect);
02253     }
02254     else
02255         event.Skip();
02256 }
02257 
02258 void wxIFMDefaultPanelPlugin::DrawTabs(wxDC &dc, wxIFMComponent *component, const wxRegion &region, const wxIFMTabArray &tabs)
02259 {
02260     wxIFMTab *tab;
02261 
02262     wxRect bg = component->GetClientRect();
02263     wxRect tabs_area;
02264     tabs_area.x = bg.x;
02265     tabs_area.y = bg.y + bg.height + 1;// - 1;//tab->m_tab->m_parent->m_margins.bottom;
02266     tabs_area.width = bg.width;
02267     tabs_area.height = m_tab_config.row_height;
02268 
02269     // paint tabs only if we need to
02270     wxRegionContain result = region.Contains(tabs_area);
02271     if( !(result == wxInRegion || result == wxPartRegion) )
02272         return;
02273 
02274     // background for tabs area
02275     dc.SetPen(m_tab_config.bg_pen);
02276     dc.SetBrush(m_tab_config.bg_brush);
02277     dc.DrawRectangle(tabs_area);
02278 
02279     // top line
02280     dc.SetPen(m_tab_config.line_pen);
02281     dc.DrawLine(tabs_area.x-1, tabs_area.y, tabs_area.x + tabs_area.width+1, tabs_area.y);
02282 
02283     wxIFMPanelTabData *tab_data;
02284     wxRect rect;
02285 
02286     //for( wxIFMTabArray::const_iterator i = tabs.begin(), end = tabs.end(); i != end; ++i )
02287     for( size_t i = 0; i < tabs.GetCount(); i++ )
02288     {
02289         //tab = *i;
02290         tab = tabs[i];
02291 
02292         if( !tab->m_visible )
02293             continue;
02294 
02295         // don't paint the tab if its not in the update region
02296         result = region.Contains(tab->m_rect);
02297         if( !(result == wxInRegion || result == wxPartRegion) )
02298             continue;
02299 
02300         rect = tab->m_rect;
02301 
02302         // draw the tab background
02303         // if the tab is not selected draw a black line above
02304         if( tab->m_active )
02305         {
02306             dc.SetBrush(m_tab_config.tab_active_bg_b);
02307             dc.SetPen(m_tab_config.tab_border_p);
02308             dc.DrawRoundedRectangle(rect.x, rect.y, rect.width, rect.height, m_tab_config.rounding_factor);
02309 
02310             dc.SetPen(m_tab_config.tab_active_bg_p);
02311             dc.DrawRectangle(rect.x, rect.y, rect.width, m_tab_config.rounding_factor);
02312 
02313             dc.SetPen(m_tab_config.tab_border_p);
02314             dc.DrawLine(rect.x, rect.y, rect.x, rect.y + m_tab_config.rounding_factor);
02315             dc.DrawLine(rect.x + rect.width - 1, rect.y, rect.x + rect.width - 1, rect.y + m_tab_config.rounding_factor);
02316         }
02317         else
02318         {
02319             dc.SetBrush(m_tab_config.tab_inactive_bg_b);
02320             dc.SetPen(m_tab_config.tab_border_p);
02321             dc.DrawRoundedRectangle(rect.x, rect.y, rect.width, rect.height, m_tab_config.rounding_factor);
02322 
02323             dc.SetPen(m_tab_config.tab_inactive_bg_p);
02324             dc.DrawRectangle(rect.x, rect.y, rect.width, m_tab_config.rounding_factor);
02325 
02326             dc.SetPen(m_tab_config.tab_border_p);
02327             dc.DrawLine(rect.x, rect.y, rect.x, rect.y + m_tab_config.rounding_factor);
02328             dc.DrawLine(rect.GetRight(), rect.y, rect.GetRight(), rect.y + m_tab_config.rounding_factor);
02329 
02330             dc.SetPen(m_tab_config.line_pen);
02331             dc.DrawLine(rect.x, rect.y, rect.x+rect.width, rect.y);
02332         }
02333 
02334         tab_data = IFM_GET_EXTENSION_DATA(tab->m_tab, wxIFMPanelTabData);
02335 
02336         // draw bitmap
02337         if(tab_data && tab_data->m_bitmap.Ok())
02338         {
02339             wxBitmap &bmp = tab_data->m_bitmap;
02340             dc.DrawBitmap(bmp, rect.x + m_tab_config.tab_padding, rect.y + (rect.height - bmp.GetHeight())/2, true);
02341             rect.x += m_tab_config.tab_padding + bmp.GetWidth();
02342         }
02343 
02344         // draw the label
02345         dc.SetFont(m_tab_config.font);
02346         dc.SetTextForeground(m_tab_config.font_color);
02347 
02348         dc.DrawText(tab->m_tab->m_name, rect.x + m_tab_config.tab_padding, rect.y + (rect.height - m_tab_config.font_height) / 2);
02349     }
02350 }
02351 
02352 void wxIFMDefaultPanelPlugin::OnComponentButtonClick(wxIFMComponentButtonEvent &event)
02353 {
02354     wxIFMComponent *component = event.GetComponent();
02355 
02356     wxASSERT_MSG(component, wxT("NULL component?"));
02357     if( !component )
02358         return;
02359 
02360     if( component->GetType() == IFM_COMPONENT_PANEL )
02361     {
02362         wxIFMComponentButton *button = event.GetButton();
02363         if( button->GetID() == IFM_COMPONENT_ID_CLOSE )
02364         {
02365             component->Show(false, true);
02366             return;
02367         }
02368         else if( button->GetID() == IFM_COMPONENT_ID_MINIMIZE )
02369         {
02370 
02372             return;
02373         }
02374         else if( button->GetID() == IFM_COMPONENT_ID_MAXIMIZE )
02375         {
02376 
02378             return;
02379         }
02380     }
02381 
02382     event.Skip();
02383 }
02384 
02385 void wxIFMDefaultPanelPlugin::OnLeftDown(wxIFMMouseEvent &event)
02386 {
02387     wxMouseEvent &evt = event.GetMouseEvent();
02388     wxPoint pos = evt.GetPosition();
02389     if( event.GetComponentType() == IFM_COMPONENT_PANEL )
02390     {
02391         wxIFMComponent *component = event.GetComponent();
02392 
02393         wxASSERT_MSG(component, wxT("NULL component?"));
02394         if( !component )
02395             return;
02396 
02397         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(component, wxIFMPanelData);
02398 
02399         wxASSERT_MSG(data, wxT("Panel with no panel data?"));
02400         if( !data )
02401             return;
02402 
02403         // see if the user clicked on a tab and select it
02404         for( size_t i = 0; i < data->m_tabs.GetCount(); i++ )
02405         //for( wxIFMTabArray::const_iterator i = data->m_tabs.begin(), end = data->m_tabs.end(); i != end; ++i )
02406         {
02407             wxIFMTab *tab = data->m_tabs[i];
02408             if( tab->m_visible && tab->m_rect.Inside(event.GetMouseEvent().GetPosition()) )
02409             {
02410                 wxIFMSelectTabEvent evt(component, tab, true);
02411                 GetIP()->ProcessPluginEvent(evt);
02412                 break;
02413             }
02414         }
02415 
02416         // now check for drag initialization hot spots which are the caption and any tab
02417         if( data->m_caption.Inside(pos) )
02418         {
02419             wxIFMInitDragEvent evt(component, component, pos);
02420             GetIP()->ProcessPluginEvent(evt);
02421         }
02422         else
02423         {
02424             // check for individual tab hits
02425             for( size_t i = 0; i < data->m_tabs.GetCount(); i++ )
02426             //for(wxIFMTabArray::iterator i = data->m_tabs.begin(), end = data->m_tabs.end(); i != end; ++i )
02427             {
02428                 wxIFMTab *tab = data->m_tabs[i];
02429                 if( tab->m_visible && tab->m_rect.Inside(pos) )
02430                 {
02431                     // if we only have one tab drag the panel instead of the tab
02432                     wxIFMComponent *drag;
02433                     if( data->m_tabs.size() == 1 )
02434                         drag = component;
02435                     else
02436                         drag = tab->m_tab;
02437 
02438                     wxIFMInitDragEvent evt(component, drag, pos);
02439                     GetIP()->ProcessPluginEvent(evt);
02440                     break;
02441                 }
02442             }
02443         }
02444     }
02445     else
02446         event.Skip();
02447 }
02448 
02449 void wxIFMDefaultPanelPlugin::OnSelectTab(wxIFMSelectTabEvent &event)
02450 {
02451     if( event.GetComponentType() == IFM_COMPONENT_PANEL )
02452     {
02453         wxIFMComponent *panel = event.GetComponent();
02454 
02455         wxASSERT_MSG(panel, wxT("NULL component?"));
02456         if( !panel )
02457             return;
02458 
02459         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(panel, wxIFMPanelData);
02460 
02461         wxASSERT_MSG(data, wxT("Tabbed panel with no tabbed panel data?"));
02462         if( !data )
02463             return;
02464 
02465         wxIFMTab *tab = event.GetTab();
02466 
02467         // don't active the current tab over again
02468         if( tab == data->m_active_tab )
02469             return;
02470 
02471         // record the new active tab
02472         data->m_active_tab = tab;
02473 
02474         // update the new tab
02475         if( event.GetUpdate() )
02476         {
02477             wxIFMUpdateComponentEvent evt(tab->m_tab, panel->GetClientRect());
02478             GetIP()->ProcessPluginEvent(evt);
02479         }
02480 
02481         // show and activate the new tab while hiding the others
02482         for( size_t i = 0; i < data->m_tabs.GetCount(); i++ )
02483         //for( wxIFMTabArray::iterator i = data->m_tabs.begin(), end = data->m_tabs.end(); i != end; ++i )
02484         {
02485             data->m_dont_hide_tab = true;
02486             data->m_tabs[i]->m_tab->Show(data->m_tabs[i] == tab, false);
02487             data->m_tabs[i]->m_active = data->m_tabs[i] == tab;
02488         }
02489 
02490         if(event.GetUpdate()) {
02491             wxIFMUpdateComponentEvent evt(panel, panel->GetRect());
02492             GetIP()->ProcessPluginEvent(evt);
02493         }
02494     }
02495     else
02496         event.Skip();
02497 }
02498 
02499 void wxIFMDefaultPanelPlugin::OnGetDesiredSize(wxIFMRectEvent &event)
02500 {
02501     /*
02502     if( event.GetComponentType() == IFM_COMPONENT_PANEL )
02503     {
02504         wxIFMComponent *panel = event.GetComponent();
02505 
02506         wxASSERT_MSG(panel, wxT("NULL component?"));
02507         if( !panel )
02508             return;
02509 
02510         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(panel, wxIFMPanelData);
02511 
02512         wxASSERT_MSG(data, wxT("Tabbed panel with no tabbed panel data?"));
02513         if( !data )
02514             return;
02515 
02516         // use the active tabs desired size
02517         event.SetRect(panel->GetConvertedRect(wxRect(wxPoint(), data->m_active_tab->GetDesiredSize()), IFM_COORDS_CLIENT, IFM_COORDS_ABSOLUTE));
02518     }
02519     else
02520     */
02521         event.Skip();
02522 }
02523 
02524 void wxIFMDefaultPanelPlugin::OnSetDesiredSize(wxIFMRectEvent &event)
02525 {
02526     if( event.GetComponentType() == IFM_COMPONENT_PANEL )
02527     {
02528         wxIFMComponent *panel = event.GetComponent();
02529 
02530         wxASSERT_MSG(panel, wxT("NULL component?"));
02531         if( !panel )
02532             return;
02533 
02534         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(panel, wxIFMPanelData);
02535 
02536         wxASSERT_MSG(data, wxT("Tabbed panel with no tabbed panel data?"));
02537         if( !data )
02538             return;
02539 
02540         // set the size for all tabs
02541         wxSize size = panel->GetConvertedRect(event.GetRect(), IFM_COORDS_ABSOLUTE, IFM_COORDS_CLIENT).GetSize();
02542 
02543         for( size_t i = 0; i < data->m_tabs.GetCount(); i++ )
02544         //for( wxIFMTabArray::iterator i = data->m_tabs.begin(), end = data->m_tabs.end(); i != end; ++i )
02545             data->m_tabs[i]->m_tab->SetDesiredSize(size);
02546 
02547         // skip to set our own desired size too
02548     }
02549 
02550     event.Skip();
02551 }
02552 
02553 void wxIFMDefaultPanelPlugin::OnGetMinSize(wxIFMRectEvent &event)
02554 {
02555     if( event.GetComponentType() == IFM_COMPONENT_PANEL )
02556     {
02557         wxIFMComponent *panel = event.GetComponent();
02558 
02559         wxASSERT_MSG(panel, wxT("NULL component?"));
02560         if( !panel )
02561             return;
02562 
02563         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(panel, wxIFMPanelData);
02564 
02565         wxASSERT_MSG(data, wxT("Tabbed panel with no tabbed panel data?"));
02566         if( !data )
02567             return;
02568 
02569         // find the largest min size of our tabs and use that
02570         wxSize final_min = panel->m_minSize;
02571 
02572         for( size_t i = 0; i < panel->m_children.GetCount(); i++ )
02573         //for( wxIFMComponentArray::iterator i = panel->m_children.begin(), end = panel->m_children.end(); i != end; ++i )
02574         {
02575             wxSize min = panel->m_children[i]->GetMinSize();
02576             if( min.x > final_min.x )
02577                 final_min.x = min.x;
02578             if( min.y > final_min.y )
02579                 final_min.y = min.y;
02580         }
02581 
02582         wxSize converted_min = panel->GetConvertedRect(wxRect(wxPoint(),final_min), IFM_COORDS_CLIENT, IFM_COORDS_ABSOLUTE).GetSize();
02583         if( final_min.x != IFM_NO_MINIMUM )
02584             final_min.x = converted_min.x;
02585         if( final_min.y != IFM_NO_MINIMUM )
02586             final_min.y = converted_min.y;
02587 
02588         event.SetSize(final_min);
02589     }
02590     else
02591         event.Skip();
02592 }
02593 
02594 void wxIFMDefaultPanelPlugin::OnGetMaxSize(wxIFMRectEvent &event)
02595 {
02596     if( event.GetComponentType() == IFM_COMPONENT_PANEL )
02597     {
02598         wxIFMComponent *panel = event.GetComponent();
02599 
02600         wxASSERT_MSG(panel, wxT("NULL component?"));
02601         if( !panel )
02602             return;
02603 
02604         wxIFMPanelData *data = IFM_GET_EXTENSION_DATA(panel, wxIFMPanelData);
02605 
02606         wxASSERT_MSG(data, wxT("Tabbed panel with no tabbed panel data?"));
02607         if( !data )
02608             return;
02609 
02610         event.Skip();
02611     }
02612     else
02613         event.Skip();
02614 }
02615 
02616 /*
02617 wxIFMComponentButtonManager implementation
02618 */
02619 wxIFMComponentButtonManager::wxIFMComponentButtonManager(wxIFMInterfacePluginBase *ip, wxIFMComponent *component)
02620     : m_ip(ip),
02621     m_component(component),
02622     m_height(0),
02623     m_hidden(false)
02624 { }
02625 
02626 wxIFMComponentButtonManager::~wxIFMComponentButtonManager()
02627 {
02628 
02629 }
02630 
02631 wxIFMInterfacePluginBase *wxIFMComponentButtonManager::GetIP()
02632 {
02633     return m_ip;
02634 }
02635 
02636 wxIFMComponent *wxIFMComponentButtonManager::GetComponent()
02637 {
02638     return m_component;
02639 }
02640 
02641 const wxPoint &wxIFMComponentButtonManager::GetPosition() const
02642 {
02643     return m_pos;
02644 }
02645 
02646 void wxIFMComponentButtonManager::Hide()
02647 {
02648     Show(false);
02649 }
02650 
02651 wxIFMComponentButton *wxIFMComponentButtonManager::AddButton(int id)
02652 {
02653     wxIFMComponentButton *btn = new wxIFMComponentButton(this, id, m_component->GetParentWindow());
02654 
02655     // size the button
02656     btn->SetSize(IFM_COMPONENT_BUTTON_X, IFM_COMPONENT_BUTTON_Y);
02657 
02658     // store the button
02659     m_buttons.push_back(btn);
02660 
02661     return btn;
02662 }
02663 
02664 void wxIFMComponentButtonManager::RemoveButton(int id)
02665 {
02666     for( int i = 0, count = m_buttons.GetCount(); i < count; ++i )
02667     //for( wxIFMComponentButtonArray::iterator i = m_buttons.begin(), end = m_buttons.end(); i != end; ++i )
02668     {
02669         if( m_buttons[i]->GetID() == id )
02670         //if( (*i)->GetID() == id )
02671         {
02672             wxIFMComponentButton *btn = m_buttons[i];
02673             m_buttons.RemoveAt(i);
02674             //delete *i;
02675             //m_buttons.erase(i);
02676             delete btn;
02677             return;
02678         }
02679     }
02680 
02681     wxFAIL_MSG(wxT("Removing a button not managed by this button manager"));
02682 }
02683 
02684 wxIFMComponentButton *wxIFMComponentButtonManager::GetButton(int id)
02685 {
02686     for( int i = 0, count = m_buttons.GetCount(); i < count; ++i )
02687     //for( wxIFMComponentButtonArray::const_iterator i = m_buttons.begin(), end = m_buttons.end(); i != end; ++i )
02688     {
02689         if( m_buttons[i]->GetID() == id )
02690         //if( (*i)->GetID() == id )
02691             return m_buttons[i];
02692             //return (*i);
02693     }
02694 
02695     return NULL;
02696 }
02697 
02698 const wxRect wxIFMComponentButtonManager::GetRect() const
02699 {
02700     wxRect rect;
02701     rect.x = m_pos.x;
02702     rect.y = m_pos.y;
02703     rect.height = m_height;
02704 
02705     for( int i = 0, count = m_buttons.GetCount(); i < count; ++i )
02706     //for( wxIFMComponentButtonArray::const_iterator i = m_buttons.begin(), end = m_buttons.end(); i != end; ++i )
02707     {
02708         rect.width += m_buttons[i]->GetRect().width;
02709         //rect.width += (*i)->GetRect().width;
02710         rect.width += IFM_COMPONENT_BUTTON_PAD;
02711     }
02712 
02713     return rect;
02714 }
02715 
02716 void wxIFMComponentButtonManager::SetPosition(const wxPoint& pos)
02717 {
02718     m_pos = pos;
02719 }
02720 
02721 void wxIFMComponentButtonManager::SetHeight(int height)
02722 {
02723     m_height = height;
02724     for( int i = 0, count = m_buttons.GetCount(); i < count; ++i )
02725     //for( wxIFMComponentButtonArray::iterator i = m_buttons.begin(), end = m_buttons.end(); i != end; ++i )
02726         m_buttons[i]->SetSize(IFM_COMPONENT_BUTTON_X, IFM_COMPONENT_BUTTON_Y);
02727         //(*i)->SetSize(IFM_COMPONENT_BUTTON_X, IFM_COMPONENT_BUTTON_X);
02728 }
02729 
02730 void wxIFMComponentButtonManager::SetParent(wxWindow *parent)
02731 {
02732     for( int i = 0, count = m_buttons.GetCount(); i < count; ++i )
02733     //for( wxIFMComponentButtonArray::iterator i = m_buttons.begin(), end = m_buttons.end(); i != end; ++i )
02734         m_buttons[i]->Reparent(parent);
02735         //(*i)->Reparent(parent);
02736 }
02737 
02738 void wxIFMComponentButtonManager::Layout()
02739 {
02740     if( m_hidden )
02741         return;
02742 
02743     wxPoint pos = m_pos;
02744     pos.y += 2;
02745 
02746     for( int i = 0, count = m_buttons.GetCount(); i < count; ++i )
02747     //for( wxIFMComponentButtonArray::iterator i = m_buttons.begin(), end = m_buttons.end(); i != end; ++i )
02748     {
02749         m_buttons[i]->SetPosition(pos);
02750         //(*i)->SetPosition(pos);
02751         pos.x += (IFM_COMPONENT_BUTTON_X + IFM_COMPONENT_BUTTON_PAD);
02752     }
02753 }
02754 
02755 void wxIFMComponentButtonManager::Show(bool show)
02756 {
02757     m_hidden = !show;
02758 
02759     for( int i = 0, count = m_buttons.GetCount(); i < count; ++i )
02760     //for( wxIFMComponentButtonArray::iterator i = m_buttons.begin(), end = m_buttons.end(); i != end; ++i )
02761         m_buttons[i]->Show(show);
02762         //(*i)->Show(show);
02763 }
02764 
02765 void wxIFMComponentButtonManager::Show(bool show, int id)
02766 {
02767     wxIFMComponentButton *btn = GetButton(id);
02768 
02769     wxASSERT_MSG(btn, wxT("invalid button id"));
02770     if( btn )
02771         btn->Show(show);
02772 }
02773 
02774 BEGIN_EVENT_TABLE(wxIFMComponentButton, wxWindow)
02775     EVT_ERASE_BACKGROUND (wxIFMComponentButton::OnEraseBg)
02776     EVT_PAINT           (wxIFMComponentButton::OnPaint)
02777     EVT_ENTER_WINDOW    (wxIFMComponentButton::OnEnterWindow)
02778     EVT_LEAVE_WINDOW    (wxIFMComponentButton::OnLeaveWindow)
02779     EVT_LEFT_DOWN       (wxIFMComponentButton::OnLeftDown)
02780     EVT_LEFT_UP         (wxIFMComponentButton::OnLeftUp)
02781     EVT_MOTION          (wxIFMComponentButton::OnMouseMove)
02782 END_EVENT_TABLE()
02783 
02784 wxIFMComponentButton::wxIFMComponentButton(wxIFMComponentButtonManager *manager, int id, wxWindow *parent)
02785     : wxWindow(parent, wxID_ANY, wxPoint(0,0), wxSize(0,0), wxNO_BORDER),
02786     m_manager(manager),
02787     m_id(id),
02788     m_hover(false),
02789     m_pressed(false),
02790     m_leftDown(false),
02791     m_bmp(NULL),
02792     m_bmpH(NULL),
02793     m_bmpP(NULL)
02794 { }
02795 
02796 wxIFMInterfacePluginBase *wxIFMComponentButton::GetIP()
02797 {
02798     return m_manager->GetIP();
02799 }
02800 
02801 int wxIFMComponentButton::GetID() const
02802 {
02803     return m_id;
02804 }
02805 
02806 bool wxIFMComponentButton::GetHover() const
02807 {
02808     return m_hover;
02809 }
02810 
02811 bool wxIFMComponentButton::GetPressed() const
02812 {
02813     return m_pressed;
02814 }
02815 
02816 void wxIFMComponentButton::SetHover(bool h)
02817 {
02818     if( h != m_hover )
02819     {
02820         m_hover = h;
02821         Refresh();
02822     }
02823 }
02824 
02825 void wxIFMComponentButton::SetPressed(bool p)
02826 {
02827     if( p != m_pressed )
02828     {
02829         m_pressed = p;
02830         Refresh();
02831     }
02832 }
02833 
02834 void wxIFMComponentButton::OnEnterWindow(wxMouseEvent &WXUNUSED(event))
02835 {
02836     SetHover(true);
02837 }
02838 
02839 void wxIFMComponentButton::OnLeaveWindow(wxMouseEvent &WXUNUSED(event))
02840 {
02841     SetHover(false);
02842 }
02843 
02844 void wxIFMComponentButton::OnPaint(wxPaintEvent &WXUNUSED(event))
02845 {
02846     wxPaintDC dc(this);
02847     int w, h;
02848 
02849     GetClientSize(&w, &h);
02850     dc.SetBrush(GetBackgroundColour());
02851     dc.SetPen(GetBackgroundColour());
02852     dc.DrawRectangle(0, 0, w, h);
02853 
02854     if( m_hover )
02855     {
02856         if( m_pressed )
02857             dc.DrawBitmap(*m_bmpP, 0, 0, true);
02858         else
02859             dc.DrawBitmap(*m_bmpH, 0, 0, true);
02860     }
02861     else
02862         dc.DrawBitmap(*m_bmp, 0, 0, true);
02863 }
02864 
02865 void wxIFMComponentButton::OnEraseBg(wxEraseEvent &WXUNUSED(event))
02866 {
02867 
02868 }
02869 
02870 void wxIFMComponentButton::OnLeftDown(wxMouseEvent &WXUNUSED(event))
02871 {
02872     m_leftDown = true;
02873     CaptureMouse();
02874 
02875     SetPressed(true);
02876 }
02877 
02878 void wxIFMComponentButton::OnLeftUp(wxMouseEvent &event)
02879 {
02880     if( m_leftDown )
02881     {
02882         m_leftDown = false;
02883         ReleaseMouse();
02884 
02885         SetPressed(false);
02886 
02887         wxRect rect = GetRect();
02888         rect.y = rect.x = 0;
02889         if( rect.Inside(event.GetPosition()) )
02890         {
02891             // send button press event
02892             wxIFMComponentButtonEvent evt(wxEVT_IFM_COMPONENTBUTTONCLICK, m_manager->GetComponent(), this);
02893             GetIP()->ProcessPluginEvent(evt);
02894         }
02895     }
02896 }
02897 
02898 void wxIFMComponentButton::OnMouseMove(wxMouseEvent &event)
02899 {
02900     if( m_leftDown )
02901     {
02902         wxRect rect = GetRect();
02903         rect.y = rect.x = 0;
02904         SetPressed(rect.Inside(event.GetPosition()));
02905     }
02906 }
02907 
02908 /*
02909     wxIFMDefaultChildData implementation
02910 */
02911 wxIFMDefaultChildData::wxIFMDefaultChildData()
02912     : wxIFMChildDataBase(),
02913     m_orientation(IFM_ORIENTATION_DEFAULT),
02914     m_index(IFM_DEFAULT_INDEX),
02915     m_newRow(false),
02916     m_tabify(false),
02917     m_pos(IFM_DEFAULT_POS),
02918     m_bitmap(wxNullBitmap)
02919 { }
02920 
02921 // docked ctor
02922 wxIFMDefaultChildData::wxIFMDefaultChildData(wxWindow *child, int type, const wxString &name,
02923         wxSize size, bool hidden, int orientation, int index, bool newRow, bool tabify, const wxBitmap &bmp)
02924     : wxIFMChildDataBase(child, type, name, size, hidden),
02925     m_orientation(orientation),
02926     m_index(index),
02927     m_newRow(newRow),
02928     m_tabify(tabify),
02929     m_pos(IFM_DEFAULT_POS),
02930     m_bitmap(bmp)
02931 { }
02932 
02933 // floating ctor
02934 wxIFMDefaultChildData::wxIFMDefaultChildData(wxWindow *child, int type, wxPoint pos, wxSize size,
02935         bool hidden, const wxString &name)
02936     : wxIFMChildDataBase(child, type, name, size, hidden),
02937     m_orientation(IFM_ORIENTATION_FLOAT),
02938     m_index(0),
02939     m_newRow(false),
02940     m_tabify(false),
02941     m_pos(pos),
02942     m_bitmap(wxNullBitmap)
02943 { }
02944 
02945 wxIFMDefaultChildData::wxIFMDefaultChildData(const wxIFMDefaultChildData &data)
02946     : wxIFMChildDataBase(data),
02947     m_orientation(data.m_orientation),
02948     m_index(data.m_index),
02949     m_newRow(data.m_newRow),
02950     m_tabify(data.m_tabify),
02951     m_pos(data.m_pos),
02952     m_bitmap(data.m_bitmap)
02953 { }
02954 
02955 wxIFMDefaultChildData::wxIFMDefaultChildData(const wxIFMChildDataBase &data)
02956     : wxIFMChildDataBase(data),
02957     m_orientation(IFM_ORIENTATION_DEFAULT),
02958     m_index(IFM_DEFAULT_INDEX),
02959     m_newRow(false),
02960     m_tabify(false),
02961     m_pos(IFM_DEFAULT_POS),
02962     m_bitmap(wxNullBitmap)
02963 { }
02964 
02965 /*
02966     wxIFMContainerData implementation
02967 */
02968 #if IFM_USE_WX_RTTI
02969 wxIFMContainerData::wxIFMContainerData()
02970     : wxIFMExtensionDataBase()/*,
02971     m_buttonManager(0,0)*/
02972 { }
02973 #endif
02974 
02975 wxIFMContainerData::wxIFMContainerData(wxIFMInterfacePluginBase *ip, wxIFMComponent *c)
02976     : wxIFMExtensionDataBase(),
02977     //m_buttonManager(ip, c),
02978     m_orientation(IFM_ORIENTATION_NONE)
02979 { }
02980 
02981 wxIFMComponentDataKeyType wxIFMContainerData::GetDataKey() const
02982 {
02983     return IFM_CONTAINER_DATA_KEY;
02984 }
02985 
02986 wxIFMComponentDataKeyType wxIFMContainerData::DataKey()
02987 {
02988     return IFM_CONTAINER_DATA_KEY;
02989 }
02990 
02991 /*
02992     wxIFMPanelTabData implementation
02993 */
02994 #if IFM_USE_WX_RTTI
02995 wxIFMPanelTabData::wxIFMPanelTabData()
02996     : wxIFMExtensionDataBase(),
02997     m_bitmap(wxNullBitmap)
02998 { }
02999 #endif
03000 
03001 wxIFMComponentDataKeyType wxIFMPanelTabData::GetDataKey() const
03002 {
03003     return IFM_PANEL_DATA_KEY;
03004 }
03005 
03006 
03007 wxIFMComponentDataKeyType wxIFMPanelTabData::DataKey()
03008 {
03009     return IFM_PANEL_DATA_KEY;
03010 }
03011 
03012 /*
03013     wxIFMPanelData implementation
03014 */
03015 wxIFMPanelData::wxIFMPanelData(wxIFMInterfacePluginBase *ip, wxIFMComponent *c)
03016     : m_button_manager(ip, c),
03017     m_active_tab_index(-1),
03018     m_active_tab(NULL),
03019     m_dont_hide_tab(false)
03020 { }
03021 
03022 wxIFMPanelData::~wxIFMPanelData()
03023 {
03024     // clean up tabs
03025     for( size_t i = 0; i < m_tabs.GetCount(); i++ )
03026     //for( wxIFMTabArray::iterator i = m_tabs.begin(), end = m_tabs.end(); i != end; ++i )
03027         delete m_tabs[i];
03028 }
03029 
03030 wxIFMComponentDataKeyType wxIFMPanelData::GetDataKey() const
03031 {
03032     return IFM_TABBED_PANEL_DATA_KEY;
03033 }
03034 
03035 wxIFMComponentDataKeyType wxIFMPanelData::DataKey()
03036 {
03037     return IFM_TABBED_PANEL_DATA_KEY;
03038 }

 

SourceForge Logo