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

OptDlg.cpp

Go to the documentation of this file.
00001 
00002 // MathGUI = a WYSIWYG equation editor + a powerful math engine      //
00003 // Copyright (C) 2003 by Francesco Montorsi                          //
00004 //                                                                   //
00005 // This library is free software; you can redistribute it and/or     //
00006 // modify it under the terms of the GNU Lesser General Public        //
00007 // License as published by the Free Software Foundation; either      //
00008 // version 2.1 of the License, or (at your option) any later         //
00009 // version.                                                          //
00010 //                                                                   //
00011 // This library is distributed in the hope that it will be useful,   //
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of    //
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the      //
00014 // GNU Lesser General Public License for more details.               //
00015 //                                                                   //
00016 // You should have received a copy of the GNU Lesser General Public  //
00017 // License along with this program; if not, write to the Free        //
00018 // Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,   //
00019 // MA 02111-1307, USA.                                               //
00020 //                                                                   //
00021 // For any comment, suggestion or feature request, please contact    //
00022 // the administrator of the project at frm@users.sourceforge.net     //
00023 //                                                                   //
00030 
00031 
00032 
00033 // optimization for GCC compiler
00034 #if defined(__GNUG__) && !defined(__APPLE__)
00035   #pragma implementation "OptDlg.h"
00036 #endif
00037 
00038 
00039 // includes
00040 #include "mg/mgprec.h"
00041 
00042 #ifndef mgPRECOMP
00043    #include "mg/OptDlg.h"
00044    #include "mg/OptBtnPanel.h"
00045    #include "mg/OptTreeCtrl.h"
00046 
00047    // the panels which can be displayed by this dialog...
00048    #include "mg/OptBasePanel.h"
00049    #include "mg/OptGeneral.h"
00050    #include "mg/OptKeyBindings.h"
00051    #include "mg/OptFontSettings.h"
00052 #endif
00053 
00054 
00055 
00056 // event table for mgOptDlg
00057 IMPLEMENT_CLASS(mgOptDlg, wxDialog )
00058 BEGIN_EVENT_TABLE(mgOptDlg,wxDialog)
00059   EVT_BUTTON( OPTIONSDLG_BTN_OK, mgOptDlg::OnOkButton )
00060   EVT_BUTTON( OPTIONSDLG_BTN_CANCEL, mgOptDlg::OnCancelButton )
00061   EVT_BUTTON( OPTIONSDLG_BTN_APPLY, mgOptDlg::OnApplyButton )
00062   EVT_TREE_SEL_CHANGED( OPTIONSDLG_TREELIST, mgOptDlg::OnItemSelected )
00063 END_EVENT_TABLE()
00064 
00065 // defines the custom command event sent to the app object when options change
00066 DEFINE_EVENT_TYPE( mgEVT_OPTIONS_CHANGED )
00067 
00068 
00069 
00070 
00071 // --------------------------------------------
00072 // mcOPTIONSDLG
00073 // --------------------------------------------
00074 
00075 mgOptDlg::mgOptDlg( wxWindow* parent, wxWindowID id, wxConfig* config )
00076 : wxDialog( parent, id, wxT("MathStudio Options"),
00077          wxDefaultPosition, wxSize( 660, 500),
00078          wxCAPTION | wxSYSTEM_MENU | wxRESIZE_BORDER )
00079 {
00080    // inits the option's panel actually displayed
00081    m_actualPanel = 0;
00082    // m_emptyPanel  = 0;
00083 
00084    // set the event handler which will receive our custom events
00085    SetClientEvtHandler(parent);
00086 
00087    // creates the button panel and the treelist control
00088    m_treeWnd   = new mgOptionsTreeCtrl( this );
00089    m_buttonWnd = new mgOptionsBtnPanel( this );
00090 
00091    CreateLayout( this );      // creates the layout objects for the tree child windows
00092    //DisplayPanel( Id_mgOptBasePanel );       // creates and displays the empy panel
00093 
00094    // selects the first children of the root node: THIS DOESN'T WORK
00095    // on wxGTK: it provokes a segmentation fault !!!!
00096    //long tmp;
00097    //wxTreeItemId n = m_treeWnd->GetRootItem();
00098    //m_treeWnd->SelectItem(m_treeWnd->GetItemData(m_treeWnd->GetFirstChild(n, tmp)));
00099 }
00100 
00102 mgOptDlg::~mgOptDlg()
00103 {
00104 }
00105 
00106 
00107 
00108 
00109 void mgOptDlg::CreateLayout( wxWindow* parent )
00110 {
00111 #ifdef OPTIONSDLG_USE_LAYOUTCONSTRAINTS
00112    // Set constraints for the tree list control: same as the parent window
00113    // with a 10 pixel margin and an absolute width of 160 pixels
00114    wxLayoutConstraints* treeLayout = new wxLayoutConstraints;
00115    wxASSERT( treeLayout );
00116 
00117    treeLayout->left.SameAs (parent, wxLeft, 10 );
00118    treeLayout->top.SameAs (parent, wxTop, 10 );
00119    treeLayout->width.Absolute ( 160 );
00120    treeLayout->bottom.SameAs( parent, wxBottom, 10);
00121    m_treeWnd->SetConstraints( treeLayout );
00122 
00123    // Set constraints for the button panel window:
00124    // The button panel is located just left of the tree list control, at the
00125    // bottom of parent window and it has an absolute height of 70 pixels
00126    // Its width is strechable to the right end of the parent
00127    wxLayoutConstraints* buttonLayout = new wxLayoutConstraints;
00128    wxASSERT( buttonLayout );
00129 
00130    buttonLayout->left.RightOf ( m_treeWnd, 10 );
00131    buttonLayout->height.Absolute ( 70 );
00132    buttonLayout->right.SameAs ( parent, wxRight, 10 );
00133    buttonLayout->bottom.SameAs( parent, wxBottom, 10);
00134    m_buttonWnd->SetConstraints( buttonLayout );
00135 
00136    // creates the layout for the option's panels
00137    // but since no windows are yet created, it does not call SetConstraints for
00138    // this object, instead it is stored in a data members and when option's panels
00139    // will be created, a newly created copy of this object is set as constraints
00140    // for the panel
00141    m_optionLayout = new wxLayoutConstraints;
00142    wxASSERT( m_optionLayout );
00143 
00144    m_optionLayout->left.RightOf ( m_treeWnd, 10 );
00145    m_optionLayout->top.SameAs( parent, wxTop, 10 );
00146    m_optionLayout->right.SameAs ( parent, wxRight, 10 );
00147    m_optionLayout->bottom.Above( m_buttonWnd, 10);
00148 
00149    // forces layout to be handled automatically by wxWidgets in OnSize() handlers
00150    SetAutoLayout( TRUE );
00151 
00152 #else
00153 
00154    // use sizers...
00155    m_mainSizer = new wxBoxSizer(wxHORIZONTAL);
00156    m_optionSizer = new wxBoxSizer(wxVERTICAL);
00157 
00158    // DisplayPanel() will prepend to this sizer the actual panel
00159    m_optionSizer->Add(m_buttonWnd, 1, wxGROW);
00160 
00161    // place in the m_mainSizer sizer of the dialog both the treectrl,
00162    // the actual panel and the OK, CANCEL, APPLY buttons
00163    m_mainSizer->Add(m_treeWnd, 2, wxGROW | wxALL, 10);
00164    m_mainSizer->Add(m_optionSizer, 5, wxGROW | wxALL, 5);
00165 
00166    SetSizer(m_mainSizer);
00167    m_mainSizer->SetSizeHints(this);
00168 
00169 #endif // OPTIONSDLG_USE_LAYOUTCONSTRAINTS
00170 
00171    // this doesn't work     :-(
00172    /*long tmp;
00173    wxTreeItemId n = m_treeWnd->GetRootItem();
00174    m_treeWnd->SelectItem(m_treeWnd->GetItemData(m_treeWnd->GetFirstChild(n, tmp)));*/
00175 }
00176 
00177 
00178 
00179 mgOptBasePanel *mgOptDlg::CreatePanel(  mgOptTreeCtrlItemData *itemData, const wxString &itemLabel )
00180 {
00181    mgLogDebug( wxT("mgOptDlg::CreatePanel() itemData=%p"), itemData );
00182    wxASSERT( itemData );
00183 
00184 #ifdef OPTIONSDLG_USE_LAYOUTCONSTRAINTS
00185    // the copy of the constraints object
00186    wxLayoutConstraints* c = new wxLayoutConstraints( *m_optionLayout );
00187    wxASSERT( c );
00188 #endif
00189 
00190    mgOptBasePanel* panel = 0;
00191 
00192 #ifdef NOT_DEFINED
00193    // this piece of code constructs a mgOptBasePanel-derived class from its
00194    // classname using wxWidgets's RTTI feature and the 'wxCreateDynamicObject()'
00195    // function.
00196    // It seems that not all platforms supports the dynamic creation of objects
00197    // so I have stripped out this code fragment
00198    // but I still leave the possibility of using this feature in the future
00199    wxString className = itemData->m_className;
00200    panel = ( mgOptBasePanel*) ::wxCreateDynamicObject( className );
00201 #endif
00202 
00203    // gets the ID of the class
00204    IdOptionsPanel id = itemData->m_classID;
00205 
00206    switch ( id )  {
00207    case Id_mgOptGeneralPanel :
00208       panel = new mgOptGeneralPanel();
00209       break;
00210    case Id_mgOptKeyBindingsPanel :
00211       panel = new mgOptKeyBindingsPanel();
00212       break;
00213    case Id_mgOptFontSettingsPanel:
00214       panel = new mgOptFontSettingsPanel();
00215       break;
00216    default :
00217       panel = NULL;
00218       break;
00219    }
00220 
00221    wxASSERT( panel );
00222 
00223 
00224    // two step creation because dynamic creation only accepts default ctor
00225    // the problem is that in the default ctor we cannot set much (for
00226    // example ew cannot call SetBackgroundColor() becasue the object is
00227    // not yet created.
00228    // We have to set backgrounds and children only when the Create function
00229    // is called.
00230    panel->Create( this, -1 );
00231 
00232    // after the windows substystem has fully created the underlaying structures
00233    // we can call the virtual Setup() function in order to let the derived
00234    // panel initialize itself
00235    panel->Setup( itemLabel );
00236 
00237 #ifdef OPTIONSDLG_USE_LAYOUTCONSTRAINTS
00238    // use constraints
00239    panel->SetConstraints( c );
00240 #endif
00241 
00242    mgLogDebug( wxT("mgOptDlg::CreatePanel() . panel created") );
00243 
00244    return panel;
00245 }
00246 
00247 void mgOptDlg::DisplayPanel( wxTreeItemId itemId )
00248 {
00249    mgLogDebug( wxT("mgOptDlg::DisplayPanel() - start\n") );
00250    wxASSERT( itemId.IsOk() );
00251 
00252    // gets the item-data structure associated with the treelist item
00253    mgOptTreeCtrlItemData *itemData =
00254       ( mgOptTreeCtrlItemData* ) m_treeWnd->GetItemData( itemId );
00255 
00256    // gets the item label
00257    wxString itemLabel = m_treeWnd->GetItemText( itemId );
00258 
00259    mgLogDebug( wxT("mgOptDlg::Display Panel() label=%s, item-data=%p"),
00260       itemLabel.c_str(), itemData );
00261 
00262    wxASSERT( itemData != 0 );
00263 
00264    // gets the panel pointer (NULL if not yet created)
00265    mgOptBasePanel*   newPanel = itemData->m_panel;
00266    mgLogDebug( wxT("mgOptDlg::DisplayPanel() - itemData=%p panel=%p classname=%s"),
00267       itemData, itemData->m_panel, (itemData->m_className).c_str() );
00268 
00269 
00270    // if newPanel == ZERO no instance of the specialized class was yet created
00271    // so creates it and stores the pointer in the item-data structure
00272    if ( newPanel == 0 )  {
00273       newPanel = CreatePanel( itemData, itemLabel );
00274       itemData->m_panel = newPanel;
00275    }
00276 
00277    // if the selected panel is the already displayed one (the user just
00278    // clicks twice upon a tree-list item), does nothing
00279    if ( m_actualPanel == newPanel )
00280       return;
00281 
00282    // hides the previously displayed panel and shows the actual one
00283    if ( m_actualPanel != 0 )
00284       m_actualPanel->Show( FALSE );
00285 
00286 #ifndef OPTIONSDLG_USE_LAYOUTCONSTRAINTS
00287 
00288    // remove old panel from sizer
00289    if (m_actualPanel)
00290       m_optionSizer->Remove(m_actualPanel);
00291 
00292    // prepend the new one
00293    m_optionSizer->Prepend(newPanel, 7, wxALL | wxGROW, 5);
00294    m_optionSizer->Layout();
00295    m_mainSizer->Layout();
00296 
00297    // this call is very important because it sets the minimum size
00298    // which is allowed for the options dlg: it's surely changed
00299    // if we changed the currently displayed panel...
00300    m_mainSizer->SetSizeHints(this);
00301 
00302    mgLogDebug( wxT("mgOptDlg::DisplayPanel() - sizer has been prepended") );
00303 
00304 #endif
00305 
00306    wxASSERT( newPanel != 0 );
00307 
00308    mgLogDebug( wxT("mgOptDlg::DisplayPanel() - showing the panel") );
00309 
00310    // refresh and center the dialog
00311    CenterOnScreen();
00312    newPanel->Show( TRUE );
00313    m_actualPanel = newPanel;
00314    Refresh();
00315 }
00316 
00317 void mgOptDlg::CommitChanges()
00318 {
00319    mgLogDebug( wxT("Edit - Options dialog box: Committing changes") );
00320    //return;   // for now,
00321 
00322    // iterate through m_treeWnd treelist's items and obtain
00323    // the m_panel data member of itemdata structure
00324    // then calls the CommitChanges() function of every panel which
00325    // returns the type of changes the panel is responsible of.
00326    // The type returned from the panel's CommitChanges function
00327    // is OR'ed with the previuos returned one.
00328    // After all panel's CommitChanges() function were called, the
00329    // cumulative type of changes is stored in the m_clientData
00330    // member of the custom event
00331    //mgOptChangedType t = OptChanged_None;
00332    //mgOptBasePanel *panel = 0;
00333    wxASSERT( m_treeWnd != 0 );
00334 
00335    int depthLevel = 0;
00336 
00337    long cookie[OPTIONSDLG_MAX_TREELIST_DEPTH];     // used for iteration
00338    wxTreeItemId rootID  = m_treeWnd->GetRootItem();
00339    wxTreeItemId childId[OPTIONSDLG_MAX_TREELIST_DEPTH];
00340 
00341    // obtains the first child of the root node and checks if
00342    // it is valid. if not, there are no items in the treelist
00343    childId[0] = m_treeWnd->GetFirstChild( rootID, cookie[0] );
00344    if ( !childId[0].IsOk() )  {
00345       mgLogDebug( wxT("mgOptDlg::CommitChanges() - no items in trelist\n") );
00346       return;
00347    }
00348 
00349    // iterates through items and sub-items.
00350    while ( 1 )  {
00351       // checks if the childId[0] is valid
00352       // otherwise, there are no more items
00353       // we checkk if the actual level child has children. Is yes,
00354       // we increse the depth level and obtain the children of the child
00355       if ( m_treeWnd->ItemHasChildren( childId[depthLevel] ))  {
00356          wxTreeItemId temp;   // the parent id
00357          ++depthLevel;
00358          wxASSERT( depthLevel < OPTIONSDLG_MAX_TREELIST_DEPTH );
00359          childId[depthLevel] = m_treeWnd->GetFirstChild( temp, cookie[depthLevel] );
00360       }
00361       else   {
00362          // the item has no children, so we do not go down the hierarchy
00363          // but we obtain the panel's pointer of the item and call its
00364          // CommitChanges function.
00365          mgOptTreeCtrlItemData *itemData =
00366             (mgOptTreeCtrlItemData*) m_treeWnd->GetItemData( childId[depthLevel] );
00367          wxASSERT( itemData != 0 );
00368 
00369          if ( itemData->m_panel != 0 )  {
00370             itemData->m_panel->CommitChanges( m_config );
00371          }
00372 
00373          // we get the next sibling of the item until no more
00374          // siblings are returned.
00375          // when no more siblings are returned we go up in the hierarchy
00376          // by decreasing the depthLevel
00377          childId[depthLevel] = m_treeWnd->GetNextSibling( childId[depthLevel]);
00378          if ( !childId[depthLevel].IsOk() )  {
00379             // no more siblings, we go up in the hierarchy
00380             --depthLevel;
00381             // the last sibling item is the child of the root node?
00382             // if yes, we are done
00383             if ( depthLevel < 0 )
00384                break;
00385          }
00386       }
00387    }
00388 
00389    // if event notification is enabled, send our custom event to the
00390    // client event handler...
00391    wxCommandEvent ev( mgEVT_OPTIONS_CHANGED );
00392    if (m_pClientEvtHandler)
00393       m_pClientEvtHandler->AddPendingEvent( ev );
00394 }
00395 
00396 
00397 
00398 void mgOptDlg::OnOkButton( wxCommandEvent &ev )
00399 {
00400    CommitChanges();
00401    EndModal( wxID_OK );
00402 }
00403 
00404 void mgOptDlg::OnCancelButton( wxCommandEvent &ev )
00405 {
00406    EndModal( wxID_CANCEL );
00407 }
00408 
00409 void mgOptDlg::OnApplyButton( wxCommandEvent &ev )
00410 {
00411    CommitChanges();
00412 }
00413 
00414 void mgOptDlg::OnItemSelected( wxTreeEvent& ev )
00415 {
00416    // gets the newly selected item ID
00417    wxTreeItemId id = ev.GetItem();
00418 
00419    // calls the DisplayPanel function in order to display the option's panel
00420    // relevant for the selected item.
00421    DisplayPanel( id );
00422 }
00423 
00424 
00425 
00426 
00427 
00428 


Documentation generated with Doxygen on Sun Feb 6 17:19:26 2005
Visit MathStudio home page for more info

[ Top ]