ToolbarsAndUserLevel/fi

Kaikkia alkuperäiseen OpenOffice.org-lähdekoodiin tällä sivulla esitettyjä muutoksia koskee:
 * Tekijänoikeudet: Eric Bachard, marraskuu 2009
 * '''LGPLv3-käyttöoikeudet ( ja voit jakaa ja/tai muokata lähdekoodia Free Software Foundation -säätiön jukaisemien GNU Lesser General Public License -ehtojen rajoissa)

Johdanto
Below, you'll find a technical description of the Toolbars depending on the User Level feature implementation. It's question there of : the C++ source code, the graphical layout - on the User Interface side, of the UNO Layout manager, of toolbars management in the sfx2 workwin, and some other technical points like read the User Level using the config manager. We suppose that the reader has the minimal knowledge to read and understand the content of what is exposed in this page.

The pre-requisites to read this article have still to be defined, but if ever the reader is not familiar with some points, we invite him to consult the OpenOffice.org wiki to complete his knowlege, and thus, to read this article in the best possible conditions.

Tavoite
Tämä ominaisuus liittyy osaamistason valintaan asetuksista ja tavoitteena on saada yksi uusi työkalupalkki tasoa kohti moduuleihin:


 * Writer;
 * Calc;
 * Draw;
 * Impress;
 * Math;
 * Chart.

Samaa työkalupalkkia käytetään jokaisessa sovelluksessa( Writer, Calc, Draw, Math, Impress, Chart). Idean mukaisesti käytetään:


 * joko oletuspalkkia ( taituri-taso)
 * tai keskitasopalkkia ( osaaja-taso)
 * tai alkutasopalkkia ( alkaja-taso).

Sääntö : vain yksi edellisistä työkalupalkeista kerrallaan on aktiivisena.

Määrittelyt
Tarpeet on kuvailtu wiki-sivulla Ideas and Suggestions (ranskaksi).

Odotettu toiminta : kun tasoa vaihdetaan asetuksista ( napsauta kuvaa sen suurentamiseksi ), päätyökalupalkki vaihtuu.



Writer (esimerkkinä)
Ehdotuksen mukaisesti tarkoituksena on saada yksi omanlaisensa palkki osaamis- tai käyttäjätasoa kohti.

Ehdotus ei koske vain Writeria, vaan ominaisuus laajennetaan muihin sovelluksiin ( odotetaan opettajien ehdotuksia).

Alkaja-taso
Tarkoitettu 8...9-vuotiaille:



Osaaja-taso
Tarkoitettu 10...11-vuotiaille:



Taituri-taso
Yli 11-vuotiaille lapsille:



Koodissa
Kehitteillä

-> OOo4Kidsiä koskevat muutokset on suojattu #ifdef OOo4Kids ... #endif -määreillä.

Käsiteltävät moduulit
In fact the feature has two sides, who must be considered there :


 * display one frame and retrieve the right toolbar, and ask the layout manager to display it correctly : sfx2, and the SfxWorkWindow are concerned
 * when changing the current user level : the layout manager, svx, and the preferences dialog box ( optgdlg.cxx ) are concerned (refresh e.g. )

Last : keep the possibility to add other toolbars (needs to be confirmed).

This is NOT the final solution : sc, sfx2, svx, svx use the same code to check the User Level in the Common.xcu file, and some code cleanup and factorization will be mandatory soon. Probably, tools or configmgr are the right place, to implement a class allowing to read in the Common.xcu, but this needs some love and investigations. Probably after 1.0

Moduuli svx
Allaolevat osat pitää muokata tiedostossa optgdlg.cxx (joka on hakemistossa svx/source/cui):


 * määritä staattinen OUStrings koodin aputekijäksi.

static const OUString sULConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); static const OUString sULAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ); static const OUString sULaNode( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Misc" ) ); static const OUString sULPropertyName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserLevel" ) ) );

Muutkin merkkijonot ovat hyödyksi:

/* mukauta työkalupalkit tasoon */

static const OUString aLayoutManagerPropName( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ) );

// The alignment bar // static const OUString sAlignmentToolbarTypeName( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/alignmentbar" ) ); // The standard toolbar static const OUString sStandardbarToolbarTypeName( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/standardbar" ) ); // The beginner toolbar (every application has its own) static const OUString sBeginnerbarToolbarTypeName( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/beginner" ) ); // The average toolbar (every application has its own) static const OUString sAveragebarToolbarTypeName( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/average" ) );


 * define setToolbarState : instantiate a Layout manager, then add ( requestElement(theToolbar) ) or remove a toolbar (destroyElement(theToolbar) )

static short setToolbarState( const OUString sSetAToolbarTypeName, bool isTrue ) {   try {       // avoids a crash if ever the user opens the prefs while the start center is the current view if ( ! (SfxViewFrame::Current) ) return -1; Reference< XPropertySet > xPropSet( SfxViewFrame::Current->GetFrame->GetFrameInterface, UNO_QUERY ); Reference< XLayoutManager > xLayoutManager;

if ( xPropSet.is ) {           Any aValue = xPropSet->getPropertyValue( aLayoutManagerPropName ); aValue >>= xLayoutManager; }

if ( !xLayoutManager.is ) return -1; else {           xLayoutManager->lock;

if ( isTrue ) xLayoutManager->requestElement( sSetAToolbarTypeName ); else xLayoutManager->destroyElement( sSetAToolbarTypeName );

// should refresh, but does not when showElement is used xLayoutManager->unlock; }   }    catch( Exception& ) {   }    return 0; }


 * initialize the toolbar state in the OfaMiscTabPage constructor : needs to retrieve the User Level in the Common.cxu.

Note: the toolbar are initialized in same time as the RadioButton.

// initialize the Radio button (User Level) switch ( getUserLevel ) {       case USER_LEVEL_BEGINNER: {	   fprintf(stdout, " %s : User level beginner \n", __func__);
 * 1) ifdef DEBUG
 * 1) endif

setToolbarState( sStandardbarToolbarTypeName, false); setToolbarState( sBeginnerbarToolbarTypeName, true ); setToolbarState( sAveragebarToolbarTypeName, false); aUserLevelBeginnerRB.SetState( TRUE ); }           break;

case USER_LEVEL_AVERAGE: {           fprintf(stdout, " %s : User level average \n", __func__);
 * 1) ifdef DEBUG
 * 1) endif

setToolbarState( sStandardbarToolbarTypeName, false); setToolbarState( sBeginnerbarToolbarTypeName, false ); setToolbarState( sAveragebarToolbarTypeName, true); aUserLevelAverageRB.SetState( TRUE ); }           break;

case USER_LEVEL_EXPERT: {           fprintf(stdout, " %s : User level expert \n", __func__); aUserLevelExpertRB.SetState( TRUE );
 * 1) ifdef DEBUG
 * 1) endif

setToolbarState( sStandardbarToolbarTypeName, true ); setToolbarState( sBeginnerbarToolbarTypeName, false ); setToolbarState( sAveragebarToolbarTypeName, false);

}           break; default: break; }
 * 1) endif // OOo4Kids


 * set the right toolbar when the User Level is modified (RadioButton) in the prefs : done in IMPL_LINK( OfaMiscTabPage, UserLevelCheckHdl_Impl, RadioButton*, pButton )

Note: to be sure,only one is set, while the two other are reset, for every user level.

IMPL_LINK( OfaMiscTabPage, UserLevelCheckHdl_Impl, RadioButton*, pButton ) {	(void) pButton; if ( aUserLevelExpertRB.IsChecked ) {       setUserLevel( USER_LEVEL_EXPERT );
 * 1) ifdef OOo4Kids

setToolbarState( sStandardbarToolbarTypeName, true ); setToolbarState( sBeginnerbarToolbarTypeName, false ); setToolbarState( sAveragebarToolbarTypeName, false); }   else if ( aUserLevelAverageRB.IsChecked ) {       setUserLevel( USER_LEVEL_AVERAGE );

setToolbarState( sStandardbarToolbarTypeName, false ); setToolbarState( sBeginnerbarToolbarTypeName, false ); setToolbarState( sAveragebarToolbarTypeName, true); }

else {       setUserLevel( USER_LEVEL_BEGINNER );

setToolbarState( sStandardbarToolbarTypeName, false ); setToolbarState( sBeginnerbarToolbarTypeName, true ); setToolbarState( sAveragebarToolbarTypeName, false); }   return 0; }

Moduuli sfx2
Everything has been done in sfx2/source/appl/workwin.cxx. The role of the SfxWorkWindow is extremely important: for every new document, the toolbars to be drawn will be checked there. Other case: when closing the preference dialog box ( Modal dialog box)

What has been done:


 * define static OUStrings as helpers.

// The standard toolbar static const OUString sStandardbarToolbarTypeName( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/standardbar" ) ); // The beginner toolbar (every application has its own) static const OUString sBeginnerbarToolbarTypeName( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/beginner" ) ); // The average toolbar (every application has its own) static const OUString sAveragebarToolbarTypeName( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/average" ) ); // Generic constants static const OUString sULConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); static const OUString sULAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) );


 * define getUserLevel to read the User Level in Common.xcu.

static short getUserLevel {   short dUserLevel = 1; // default is beginner try {	// get service provider Reference< XMultiServiceFactory > xSMgr( vcl::unohelper::GetMultiServiceFactory ); // create configuration hierachical access name if( xSMgr.is ) {           try {               Reference< XMultiServiceFactory > xConfigProvider(                    Reference< XMultiServiceFactory >( xSMgr->createInstance( sULConfigSrvc ), UNO_QUERY )                   ); if( xConfigProvider.is ) {                   Sequence< Any > aArgs(1); PropertyValue aVal; aVal.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) ); aVal.Value <<= OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Misc" ) ); aArgs.getArray[0] <<= aVal; Reference< XNameAccess > xConfigAccess(                       Reference< XNameAccess >( xConfigProvider->createInstanceWithArguments( sULAccessSrvc, aArgs ), UNO_QUERY )                       ); if( xConfigAccess.is ) {                       try {                           short bValue = 1; Any aAny = xConfigAccess->getByName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserLevel" ) ) ); if( aAny >>= bValue ) dUserLevel = bValue; }                       catch( NoSuchElementException& ) {                       }                        catch( WrappedTargetException& ) {                       }                    }                }            }            catch( Exception& ) {           }        }    }    catch( WrappedTargetException& ) {   }    return dUserLevel; }


 * add new ids, and names in the pToolBarResToName[] who will be used there.

Note: random values ... found no information in the code.

static const ResIdToResName pToolBarResToName[] = {   { 558,      "fullscreenbar"        }, { 560,     "standardbar",         },

...

{ 20001,   "beginner"      },      //writer { 20002,   "average"       },      //writer
 * 1) ifdef OOo4Kids
 * 1) endif

...


 * Read the User Level in the Common.xcu, and set the toolbars in SfxFrameWorkWin_Impl::UpdateObjectBars_Impl

Note: unlock the LayoutManager, triggers the refresh, but when the User Level is modified in the prefs, the refresh is triggered only when the dialog box (basically a modal window) is closed.

....

void SfxWorkWindow::UpdateObjectBars_Impl {

short int nUserLevel = getUserLevel; rtl::OUString aTbxId( m_aTbxTypeName ); aTbxId += GetResourceURLFromResId( aObjBarList[n].nId );
 * 1) ifdef OOo4Kids

switch ( nUserLevel ) {           case USER_LEVEL_BEGINNER: {               fprintf(stdout, " %s : User level beginner \n", __func__); fprintf(stdout, "nId = %d \n", nId ); fprintf(stdout, "aTbxId = %s \n", dbg_dump( aTbxId) ); //xLayoutManager->showElement( sBeginnerbarToolbarTypeName ); xLayoutManager->requestElement( sBeginnerbarToolbarTypeName ); xLayoutManager->destroyElement( sAveragebarToolbarTypeName ); xLayoutManager->destroyElement( sStandardbarToolbarTypeName ); }               break;
 * 1) ifdef DEBUG
 * 1) endif

case USER_LEVEL_AVERAGE: {               fprintf(stdout, " %s : User level average \n", __func__); fprintf(stdout, " nId = %d \n", nId ); //xLayoutManager->showElement( sAveragebarToolbarTypeName ); xLayoutManager->requestElement( sAveragebarToolbarTypeName ); xLayoutManager->destroyElement( sBeginnerbarToolbarTypeName ); xLayoutManager->destroyElement( sStandardbarToolbarTypeName ); }               break;
 * 1) ifdef DEBUG
 * 1) endif

case USER_LEVEL_EXPERT: {               fprintf(stdout, " %s : User level expert \n", __func__); fprintf(stdout, " nId = %d \n", nId ); //xLayoutManager->showElement( sStandardbarToolbarTypeName ); xLayoutManager->requestElement( sStandardbarToolbarTypeName ); xLayoutManager->destroyElement( sBeginnerbarToolbarTypeName ); xLayoutManager->destroyElement( sAveragebarToolbarTypeName ); }               break;
 * 1) ifdef DEBUG
 * 1) endif

default: break; }
 * 1) endif // OOo4Kids

...

}