1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: editor.cxx,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
48 #include <com/sun/star/awt/WindowAttribute.hpp>
49 #include <com/sun/star/awt/XLayoutConstrains.hpp>
50 #include <com/sun/star/awt/XLayoutContainer.hpp>
51 #include <com/sun/star/awt/XToolkit.hpp>
52 #include <com/sun/star/awt/XVclWindowPeer.hpp>
53 #include <com/sun/star/awt/XWindow.hpp>
54 #include <com/sun/star/awt/XWindowPeer.hpp>
55 #include <rtl/strbuf.hxx>
56 #include <rtl/ustrbuf.hxx>
57 #include <toolkit/helper/property.hxx>
58 #include <vcl/lstbox.h>
60 using namespace layout::css
;
67 #include <layout/core/helper.hxx>
68 #include <layout/core/root.hxx>
69 #include <layout/core/helper.hxx>
71 // TODO: automatically generated
73 const char *pLabel
, *pName
, *pIconName
;
75 static const WidgetSpec WIDGETS_SPECS
[] = {
76 { "Label", "fixedtext" , "sc_label.png", false },
77 { "Button", "pushbutton" , "sc_pushbutton.png", false },
78 { "Radio Button", "radiobutton" , "sc_radiobutton.png", false },
79 { "Check Box", "checkbox" , "sc_checkbox.png", false },
80 { "Line Edit", "edit" , "sc_edit.png", false },
81 { "Numeric Field", "numericfield", "sc_numericfield.png", false },
82 { "List Box ", "listbox" , NULL
, false },
84 { "Hor Box", "hbox" , NULL
, true },
85 { "Ver Box", "vbox" , NULL
, true },
86 { "Table", "table" , NULL
, true },
87 { "Alignment", "align" , NULL
, true },
88 { "Tab Control", "tabcontrol" , NULL
, true },
89 { "Hor Splitter", "hsplitter" , NULL
, true },
90 { "Ver Splitter", "vsplitter" , NULL
, true },
91 { "Scroller", "scroller" , NULL
, true },
93 const int WIDGETS_SPECS_LEN
= sizeof (WIDGETS_SPECS
) / sizeof (WidgetSpec
);
95 using namespace layout
;
96 using namespace layoutimpl
;
97 namespace css
= ::com::sun::star
;
99 static rtl::OUString
anyToString (uno::Any value
)
103 switch (value
.getValueTypeClass()) {
104 case uno::TypeClass_STRING
:
105 return value
.get
<rtl::OUString
>();
106 case uno::TypeClass_CONSTANT
:
107 return rtl::OUString::valueOf (value
.get
<sal_Int32
>());
108 case uno::TypeClass_LONG
:
109 return rtl::OUString::valueOf (value
.get
<sal_Int64
>());
110 case uno::TypeClass_SHORT
:
111 // FIXME: seems broken
112 return rtl::OUString::valueOf ((sal_Int32
) value
.get
<short>());
114 case uno::TypeClass_FLOAT
:
115 return rtl::OUString::valueOf (value
.get
<float>());
116 case uno::TypeClass_DOUBLE
:
117 return rtl::OUString::valueOf (value
.get
<double>());
119 case uno::TypeClass_BOOLEAN
:
121 bool val
= value
.get
<sal_Bool
>();
122 return rtl::OUString( val
? "1" : "0", 1, RTL_TEXTENCODING_ASCII_US
);
124 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
126 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) );*/
133 return rtl::OUString();
136 static inline long anyToNatural (uno::Any value
)
137 { return sal::static_int_cast
<long>(anyToString( value
).toInt64()); }
138 static inline double anyToDecimal (uno::Any value
)
139 { return anyToString( value
).toDouble(); }
141 /* XLayoutContainer/XLayoutConstrains are a bit of a hasle to work with.
143 class Widget
: public layoutimpl::LayoutWidget
145 friend class EditorRoot
;
148 std::vector
< Widget
*> maChildren
;
152 rtl::OUString mrLabel
, mrUnoName
;
154 // TODO: store original properties. And some property handling methods.
156 layoutimpl::PropList maOriProps
, maOriChildProps
;
160 // to be used to wrap the root
161 Widget( uno::Reference
< awt::XLayoutConstrains
> xImport
, const char *label
)
162 : mpParent( 0 ), mbForeign( true )
165 mxContainer
= uno::Reference
< awt::XLayoutContainer
>( mxWidget
, uno::UNO_QUERY
);
167 mrLabel
= rtl::OUString( label
, strlen( label
), RTL_TEXTENCODING_UTF8
);
170 // FIXME: this code is meant to import a XML file. Just use the importer,
171 // then pass the root widget. But information like the ID string is lost.
172 // So, this needs to be more closely tight to the importer.
173 uno::Sequence
< uno::Reference
< awt::XLayoutConstrains
> > aChildren
;
174 for ( int i
= 0; i
< aChildren
.getLength(); i
++ )
176 Widget
*pChild
= new Widget( aChildren
[ i
], "---" );
177 maChildren
.push_back( pChild
);
178 pChild
->mpParent
= this;
183 Widget( rtl::OUString id
, uno::Reference
< awt::XToolkit
> xToolkit
,
184 uno::Reference
< awt::XLayoutContainer
> xParent
,
185 rtl::OUString unoName
, long nAttrbs
)
186 : mpParent( 0 ), mbForeign( false ), mrId( id
),
187 mnOriAttrbs( nAttrbs
)
189 while ( xParent
.is() && !uno::Reference
< awt::XWindow
>( xParent
, uno::UNO_QUERY
).is() )
191 uno::Reference
< awt::XLayoutContainer
> xContainer( xParent
, uno::UNO_QUERY
);
192 assert( xContainer
.is() );
193 xParent
= uno::Reference
< awt::XLayoutContainer
>( xContainer
->getParent(), uno::UNO_QUERY
);
196 mxWidget
= WidgetFactory::createWidget( xToolkit
, xParent
, unoName
, nAttrbs
);
197 assert( mxWidget
.is() );
198 mxContainer
= uno::Reference
< awt::XLayoutContainer
>( mxWidget
, uno::UNO_QUERY
);
200 mrLabel
= mrUnoName
= unoName
;
201 // try to get a nicer label for the widget
202 for ( int i
= 0; i
< WIDGETS_SPECS_LEN
; i
++ )
203 if ( unoName
.equalsAscii( WIDGETS_SPECS
[ i
].pName
) )
205 const char *label
= WIDGETS_SPECS
[ i
].pLabel
;
206 mrLabel
= rtl::OUString( label
, strlen( label
), RTL_TEXTENCODING_UTF8
);
210 // set default Text property
211 // TODO: disable editing of text fields, check boxes selected, etc...
213 uno::Reference
< awt::XVclWindowPeer
> xVclPeer( mxWidget
, uno::UNO_QUERY
)
214 if ( xVclPeer
.is() ) // XVclWindowPeer ignores missing / incorrect properties
216 //FIXME: it looks odd on widgets like NumericField seeing text which is deleted
217 // when you interact with it... We can avoid it for those widgets, by doing a getProp
218 // of "Text" and check if it is empty or not.
220 xVclPeer
->setProperty( rtl::OUString::createFromAscii( "Text" ),
221 uno::makeAny( rtl::OUString::createFromAscii( "new widget" ) ) );
224 // store original properties
226 PropertyIterator
it( this, WINDOW_PROPERTY
);
227 while ( it
.hasNext() )
229 beans::Property prop
= it
.next();
230 rtl::OUString
name( prop
.Name
);
231 rtl::OUString
value( getProperty( name
, WINDOW_PROPERTY
) );
233 fprintf(stderr
, "original property: %s = %s\n", OUSTRING_CSTR(name
), OUSTRING_CSTR(value
));
235 std::pair
< rtl::OUString
, rtl::OUString
> pair( name
, value
);
236 maOriProps
.push_back( pair
);
244 for ( std::vector
< Widget
*>::const_iterator it
= maChildren
.begin();
245 it
!= maChildren
.end(); it
++ )
249 uno::Reference
< lang::XComponent
> xComp( mxWidget
, uno::UNO_QUERY
);
251 // some widgets, like our containers, don't implement this interface...
256 uno::Reference
< awt::XLayoutConstrains
> impl()
262 virtual bool addChild( LayoutWidget
*pChild
)
264 return addChild( static_cast< Widget
* >( pChild
) );
267 virtual void setProperties( const PropList
&rProps
)
269 // maOriProps = rProps;
270 LayoutWidget::setProperties( rProps
);
273 virtual void setChildProperties( LayoutWidget
*pChild
, const PropList
&rProps
)
275 maOriChildProps
= rProps
;
276 LayoutWidget::setChildProperties( pChild
, rProps
);
287 if ( maChildren
.empty() )
289 return maChildren
.front();
296 int pos
= mpParent
->getChildPos( this );
297 return mpParent
->getChild( pos
+1 );
306 int pos
= mpParent
->getChildPos( this );
307 return mpParent
->getChild( pos
-1 );
313 bool addChild( Widget
*pChild
, int pos
= 0xffff )
315 if ( !mxContainer
.is() )
318 uno::Sequence
< uno::Reference
< awt::XLayoutConstrains
> > aChildren
;
319 aChildren
= mxContainer
->getChildren();
320 int nChildrenLen
= aChildren
.getLength();
322 // ugly, but let's check if the container is next to full...
324 mxContainer
->addChild( pChild
->mxWidget
);
326 catch( awt::MaxChildrenException ex
) {
330 if ( pos
< nChildrenLen
)
331 { // if its on the middle, we need to make space for it
332 mxContainer
->removeChild( pChild
->mxWidget
);
333 for ( int i
= pos
; i
< nChildrenLen
; i
++ )
334 mxContainer
->removeChild( aChildren
[ i
] );
335 mxContainer
->addChild( pChild
->mxWidget
);
336 for ( int i
= pos
; i
< nChildrenLen
; i
++ )
337 mxContainer
->addChild( aChildren
[ i
] );
338 maChildren
.insert( maChildren
.begin()+pos
, pChild
);
341 maChildren
.push_back( pChild
);
343 assert( pChild
->mpParent
== NULL
);
344 pChild
->mpParent
= this;
346 // store container props
348 pChild
->maOriChildProps
.clear();
349 PropertyIterator
it( pChild
, CONTAINER_PROPERTY
);
350 while ( it
.hasNext() )
352 beans::Property prop
= it
.next();
353 rtl::OUString
name( prop
.Name
);
355 rtl::OUString
value( pChild
->getProperty( name
, CONTAINER_PROPERTY
) );
356 std::pair
< rtl::OUString
, rtl::OUString
> pair( name
, value
);
357 pChild
->maOriChildProps
.push_back( pair
);
358 } catch ( beans::UnknownPropertyException
&rEx
) {
359 fprintf (stderr
, "ERROR: widget reports that it has a property it cannot return: '%s' this normally means that someone screwed up their PROPERTY_SET_INFO macro usage.\n",
360 rtl::OUStringToOString (rEx
.Message
, RTL_TEXTENCODING_UTF8
).getStr());
368 bool removeChild( Widget
*pChild
)
370 if ( !mxContainer
.is() || pChild
->mpParent
!= this )
373 mxContainer
->removeChild( pChild
->mxWidget
);
375 unsigned int pos
= getChildPos( pChild
);
376 if ( pos
< maChildren
.size() )
377 maChildren
.erase( maChildren
.begin()+pos
);
378 pChild
->mpParent
= NULL
;
383 bool swapWithChild( Widget
*pChild
)
385 if ( !pChild
->isContainer() )
388 // remove all child's childrens, and try to add them here
389 removeChild( pChild
);
391 // keep a copy for failure
392 std::vector
< Widget
*> aChildren
= maChildren
;
393 std::vector
< Widget
*> aChildChildren
= pChild
->maChildren
;
395 for ( std::vector
< Widget
*>::const_iterator it
= aChildChildren
.begin();
396 it
!= aChildChildren
.end(); it
++ )
397 pChild
->removeChild( *it
);
399 for ( std::vector
< Widget
*>::const_iterator it
= aChildChildren
.begin();
400 it
!= aChildChildren
.end(); it
++ )
401 if ( !addChild( *it
) )
403 for ( std::vector
< Widget
*>::const_iterator jt
= aChildChildren
.begin();
406 for ( std::vector
< Widget
*>::const_iterator jt
= aChildChildren
.begin();
407 jt
!= aChildChildren
.end(); jt
++ )
408 pChild
->addChild( *jt
);
412 Widget
*pParent
= up();
416 pParent
->removeChild( this );
417 pParent
->addChild( pChild
);
419 pChild
->addChild( this );
423 unsigned int getChildPos( Widget
*pChild
)
426 for ( std::vector
< Widget
*>::const_iterator it
= maChildren
.begin();
427 it
!= maChildren
.end(); it
++, i
++ )
433 Widget
*getChild( int pos
)
435 if ( pos
>= 0 && pos
< (signed) maChildren
.size() )
436 return *(maChildren
.begin() + pos
);
441 { return mxContainer
.is(); }
442 unsigned int getChildrenLen()
443 { return maChildren
.size(); }
445 rtl::OUString
getLabel() const
447 rtl::OUString
getUnoName() const
448 { return mrUnoName
; }
453 for ( Widget
*pWidget
= mpParent
; pWidget
; pWidget
= pWidget
->mpParent
)
459 WINDOW_PROPERTY
, CONTAINER_PROPERTY
, WINBITS_PROPERTY
462 static rtl::OUString
findProperty( const PropList
&props
, rtl::OUString propName
)
464 for ( PropList::const_iterator it
= props
.begin(); it
!= props
.end(); it
++ )
465 if ( it
->first
.equalsIgnoreAsciiCase( propName
) )
468 fprintf(stderr
, "Serious error: property '%s' not found\n", OUSTRING_CSTR(propName
));
470 return rtl::OUString();
473 rtl::OUString
getOriginalProperty( rtl::OUString rPropName
, PropertyKind rKind
)
475 rtl::OUString rValue
;
477 case WINDOW_PROPERTY
:
478 rValue
= findProperty( maOriProps
, rPropName
);
480 case CONTAINER_PROPERTY
:
481 rValue
= findProperty( maOriChildProps
, rPropName
);
483 case WINBITS_PROPERTY
:
491 rtl::OUString
getProperty( rtl::OUString rPropName
, PropertyKind rKind
)
493 rtl::OUString rValue
;
495 case WINDOW_PROPERTY
:
496 rValue
= anyToString( layoutimpl::prophlp::getProperty( mxWidget
, rPropName
) );
498 case CONTAINER_PROPERTY
:
500 rValue
= anyToString( layoutimpl::prophlp::getProperty(
501 mpParent
->mxContainer
->getChildProperties( mxWidget
), rPropName
) );
503 case WINBITS_PROPERTY
:
511 bool isPropertyTouched( rtl::OUString propName
, PropertyKind rKind
)
513 rtl::OUString oriValue
= getOriginalProperty( propName
, rKind
);
514 rtl::OUString newValue
= getProperty( propName
, rKind
);
515 bool isTouched
= oriValue
!= newValue
;
517 fprintf(stderr
, "is property '%s' touched? %s (%s vs %s)\n", OUSTRING_CSTR(propName
), isTouched
? "yes" : "no", OUSTRING_CSTR(oriValue
), OUSTRING_CSTR(newValue
));
522 using LayoutWidget::setProperty
;
524 void setProperty( rtl::OUString rPropName
, PropertyKind rKind
, uno::Any rValue
)
527 case WINDOW_PROPERTY
:
528 layoutimpl::prophlp::setProperty( mxWidget
, rPropName
, rValue
);
530 case CONTAINER_PROPERTY
:
532 layoutimpl::prophlp::setProperty(
533 mpParent
->mxContainer
->getChildProperties( mxWidget
), rPropName
, rValue
);
535 case WINBITS_PROPERTY
:
541 struct PropertyIterator
{
544 uno::Sequence
< beans::Property
> maProps
;
547 PropertyIterator( Widget
*pWidget
, PropertyKind rKind
)
548 : mrKind( rKind
), nPropIt( 0 )
552 case WINDOW_PROPERTY
:
553 if ( layoutimpl::prophlp::canHandleProps( pWidget
->mxWidget
) )
555 uno::Reference
< beans::XPropertySetInfo
> xInfo
556 = layoutimpl::prophlp::queryPropertyInfo( pWidget
->mxWidget
);
560 maProps
= xInfo
->getProperties();
563 case CONTAINER_PROPERTY
:
564 if ( pWidget
->mpParent
)
566 uno::Reference
< beans::XPropertySet
>xParentSet(
567 pWidget
->mpParent
->mxContainer
->getChildProperties( pWidget
->mxWidget
) );
568 if ( xParentSet
.is())
570 uno::Reference
< beans::XPropertySetInfo
> xInfo( xParentSet
->getPropertySetInfo() );
572 maProps
= xInfo
->getProperties();
576 case WINBITS_PROPERTY
:
584 return nPropIt
< maProps
.getLength();
587 beans::Property
next()
589 /* rtl::OUString propName, propValue;
590 propName = maProps[ nPropIt ];
591 propValue = getProperty( propName, mrKind, false);
593 return std::pair< rtl::OUString, rtl::OUString > propPair( propName, propValue );*/
594 return maProps
[ nPropIt
++ ];
599 class EditorRoot
: public layoutimpl::LayoutRoot
{
603 EditorRoot( const uno::Reference
< lang::XMultiServiceFactory
>& xFactory
,
605 : layoutimpl::LayoutRoot( xFactory
), mpParent( pParent
)
610 virtual layoutimpl::LayoutWidget
*create( rtl::OUString id
, const rtl::OUString unoName
,
611 long attrbs
, uno::Reference
< awt::XLayoutContainer
> xParent
)
613 if ( unoName
.compareToAscii( "dialog" ) == 0 )
616 // TODO: go through specs to map unoName to a more human-readable label
617 Widget
*pWidget
= new Widget( id
, mxToolkit
, xParent
, unoName
, attrbs
);
618 if ( !mxWindow
.is() )
619 mxWindow
= uno::Reference
< awt::XWindow
>( pWidget
->getPeer(), uno::UNO_QUERY
);
621 if ( pWidget
->mxContainer
.is() )
622 pWidget
->mxContainer
->setLayoutUnit( mpParent
->mxContainer
->getLayoutUnit() );
628 /* Working with the layout in 1D, as if it was a flat list. */
631 Widget
*next( Widget
*pWidget
)
634 pNext
= pWidget
->down();
635 if ( pNext
) return pNext
;
636 pNext
= pWidget
->next();
637 if ( pNext
) return pNext
;
638 for ( Widget
*pUp
= pWidget
->up(); pUp
!= NULL
; pUp
= pUp
->up() )
639 if ( (pNext
= pUp
->next()) != NULL
)
645 Widget *prev( Widget *pWidget )
648 pPrev = pWidget->prev();
650 return pWidget->up();
652 Widget *pBottom = pPrev->down();
655 while ( pBottom->down() || pBottom->next() )
657 for ( Widget *pNext = pBottom->next(); pNext; pNext = pNext->next() )
659 Widget *pDown = pBottom->down();
669 bool moveWidget( Widget
*pWidget
, bool up
/*or down*/ )
671 // Keep child parent&pos for in case of failure
672 Widget
*pOriContainer
= pWidget
->up();
673 unsigned int oriChildPos
= pOriContainer
->getChildPos( pWidget
);
675 // Get parent&sibling before removing it, since relations get cut
676 Widget
*pSibling
= up
? pWidget
->prev() : pWidget
->next();
677 Widget
*pContainer
= pWidget
->up();
681 // try to swap with parent or child
682 // We need to allow for this at least for the root node...
687 if ( pContainer
->swapWithChild( pWidget
) )
692 // TODO: this is a nice feature, but we probably want to do it explicitely...
694 if ( pWidget
->down() && pWidget
->swapWithChild( pWidget
->down() ) )
700 pContainer
->removeChild( pWidget
);
702 // if has up sibling -- append to it, else swap with it
705 if ( pSibling
->addChild( pWidget
, up
? 0xffff : 0 ) )
708 unsigned int childPos
= pContainer
->getChildPos( pSibling
);
709 if ( pContainer
->addChild( pWidget
, childPos
+ (up
? 0 : 1) ) )
710 return true; // should always be succesful
712 // go through parents -- try to get prepended to them
715 for ( ; pContainer
&& pContainer
->up(); pContainer
= pContainer
->up() )
717 unsigned int childPos
= pContainer
->up()->getChildPos( pContainer
);
718 if ( pContainer
->up()->addChild( pWidget
, childPos
+ (up
? 0 : 1) ) )
723 // failed -- try to get it to its old position
724 if ( !pOriContainer
->addChild( pWidget
, oriChildPos
) )
726 // a parent should never reject a child back. but if it ever
727 // happens, just kill it, we don't run an orphanate here ;P
734 // NOTE: root is considered to be number -1
735 Widget
*get( Widget
*pRoot
, int nb
)
738 for ( it
= pRoot
; it
!= NULL
&& nb
>= 0; it
= next( it
) )
743 int get( Widget
*pRoot
, Widget
*pWidget
)
747 for ( it
= pRoot
; it
!= NULL
&& it
!= pWidget
; it
= next( it
) )
753 //** PropertiesList widget
755 class PropertiesList
: public layout::Table
759 friend class PropertiesList
;
761 /* wrapper between the widget and Any */
764 DECL_LINK( ApplyPropertyHdl
, layout::Window
* );
765 DECL_LINK( FlagToggledHdl
, layout::CheckBox
* );
767 AnyWidget( Widget
*pWidget
, rtl::OUString aPropName
, Widget::PropertyKind aPropKind
)
768 : mpWidget( pWidget
), maPropName( aPropName
), maPropKind( aPropKind
)
771 mbBlockFlagCallback
= false;
778 fprintf(stderr
, "~AnyWidget\n");
782 void save( uno::Any aValue
)
784 mpWidget
->setProperty( maPropName
, maPropKind
, aValue
);
790 bool flag
= mpWidget
->isPropertyTouched( maPropName
, maPropKind
);
792 if ( mpFlag
&& mpFlag
->IsChecked() != (BOOL
)flag
)
794 CheckFlag( flag
, true );
798 void CheckFlag( bool bValue
, bool bBlockCallback
)
800 if ( bBlockCallback
)
801 mbBlockFlagCallback
= true;
802 mpFlag
->Check( bValue
);
803 mbBlockFlagCallback
= false;
806 bool bFirstGet
; // HACK
807 rtl::OUString
getValue()
809 // return mpWidget->getOriProperty( maPropName );
811 if ( bFirstGet
) // king of ugliness
812 value
= mpWidget
->getProperty( maPropName
, maPropKind
);
814 value
= mpWidget
->getOriginalProperty( maPropName
, maPropKind
);
819 // FIXME: wrapper should have a base class for this...
820 virtual layout::Window
*getWindow() = 0;
821 virtual layout::Container
*getContainer() { return NULL
; }
823 virtual void load() = 0;
824 virtual void store() = 0;
827 rtl::OUString maPropName
;
828 Widget::PropertyKind maPropKind
;
829 layout::CheckBox
*mpFlag
;
830 bool mbBlockFlagCallback
;
833 struct AnyEdit
: public AnyWidget
, layout::HBox
835 layout::Edit
*mpEdit
;
837 layout::PushButton
*mpExpand
;
838 DECL_LINK( ExpandEditHdl
, layout::PushButton
* );
840 // so we can create widgets (like transforming the Edit into a
842 layout::Window
*mpWinParent
;
844 AnyEdit( Widget
*pWidget
, rtl::OUString aPropName
,
845 Widget::PropertyKind aPropKind
, layout::Window
*pWinParent
)
846 : AnyWidget( pWidget
, aPropName
, aPropKind
), layout::HBox( 0, false ), mpWinParent( pWinParent
)
849 mpExpand
= new layout::PushButton( pWinParent
, WB_TOGGLE
);
850 mpExpand
->SetToggleHdl( LINK( this, AnyEdit
, ExpandEditHdl
) );
851 setAsMultiLine( false );
862 virtual layout::Window
*getWindow()
864 virtual layout::Container
*getContainer()
867 void setAsMultiLine( bool bMultiLine
)
873 text
= mpEdit
->GetText();
874 printf("Remove mpEdit and expand\n");
882 mpEdit
= new layout::Edit( mpWinParent
, WB_BORDER
);
883 mpExpand
->SetText( String::CreateFromAscii( "-" ) );
887 mpEdit
= new layout::Edit( mpWinParent
, WB_BORDER
);
888 mpExpand
->SetText( String::CreateFromAscii( "+" ) );
891 mpEdit
->SetText( text
);
892 mpEdit
->SetModifyHdl( LINK( this, AnyEdit
, ApplyPropertyHdl
) );
894 Add( mpEdit
, true, true, 0 );
895 Add( mpExpand
, false, true, 0 );
897 mbMultiLine
= bMultiLine
;
901 // TODO: make this global... We'll likely need it for export...
903 const char *ori
, *dest
;
905 static rtl::OUString
stringReplace( rtl::OUString _str
,
908 const sal_Unicode
*str
= _str
.getStr();
909 rtl::OUStringBuffer buf
;
911 for ( i
= 0; i
< _str
.getLength(); i
++ )
913 for ( j
= 0; trans
[ j
].ori
; j
++ )
915 const char *ori
= trans
[ j
].ori
;
916 for ( k
= 0; ori
[ k
] && i
+k
< _str
.getLength(); k
++ )
917 if ( ori
[ k
] != str
[ i
+k
] )
922 buf
.appendAscii( trans
[ j
].dest
);
927 buf
.append( str
[ i
] );
929 return buf
.makeStringAndClear();
936 // replace end of lines by "\\n" strings
937 Translate trans
[] = {
938 { "\\", "\\\\" }, { "\n", "\\n" }, { 0, 0 }
940 rtl::OUString str
= anyToString( getValue() );
941 str
= stringReplace( str
, trans
);
944 mpEdit
->SetText( getValue() );
951 // replace "\\n" strings by actual end of lines
952 Translate trans
[] = {
953 { "\\\\", "\\" }, { "\\n", "\n" },
954 { "\\", "" }, { 0, 0 }
956 rtl::OUString str
= GetText();
957 str
= stringReplace( str
, trans
);
958 save( uno::makeAny( str
) );
960 save( uno::makeAny( (rtl::OUString
) mpEdit
->GetText() ) );
964 struct AnyInteger
: public AnyWidget
, NumericField
966 AnyInteger( Widget
*pWidget
, rtl::OUString aPropName
,
967 Widget::PropertyKind aPropKind
, Window
*pWinParent
)
968 : AnyWidget( pWidget
, aPropName
, aPropKind
), NumericField( pWinParent
, WB_SPIN
|WB_BORDER
)
971 SetModifyHdl( LINK( this, AnyInteger
, ApplyPropertyHdl
) );
974 virtual Window
*getWindow()
979 OUString text
= getValue();
980 SetText( text
.getStr() );
987 fprintf(stderr
, "store number: %ld\n", rtl::OUString( GetText() ).toInt64());
989 save( uno::makeAny( rtl::OUString( GetText() ).toInt64() ) );
993 struct AnyFloat
: public AnyInteger
995 AnyFloat( Widget
*pWidget
, rtl::OUString aPropName
,
996 Widget::PropertyKind aPropKind
, Window
*pWinParent
)
997 : AnyInteger( pWidget
, aPropName
, aPropKind
, pWinParent
)
1000 virtual void store()
1002 save( uno::makeAny( rtl::OUString( GetText() ).toDouble() ) );
1006 struct AnyCheckBox
: public AnyWidget
, layout::CheckBox
1008 AnyCheckBox( Widget
*pWidget
, rtl::OUString aPropName
,
1009 Widget::PropertyKind aPropKind
, layout::Window
*pWinParent
)
1010 : AnyWidget( pWidget
, aPropName
, aPropKind
), layout::CheckBox( pWinParent
)
1012 // adding some whitespaces to make the hit area larger
1013 // SetText( String::CreateFromAscii( "" ) );
1015 SetToggleHdl( LINK( this, AnyWidget
, ApplyPropertyHdl
) );
1018 virtual ~AnyCheckBox()
1021 fprintf(stderr
, "~AnyCheckBox\n");
1025 virtual layout::Window
*getWindow()
1031 fprintf(stderr
, "loading boolean value\n");
1033 Check( getValue().toInt64() != 0 );
1038 virtual void store()
1040 save( uno::makeAny( IsChecked() ) );
1046 SetText( String::CreateFromAscii( IsChecked() ? "true" : "false" ) );
1050 struct AnyListBox
: public AnyWidget
, layout::ListBox
1052 AnyListBox( Widget
*pWidget
, rtl::OUString aPropName
,
1053 Widget::PropertyKind aPropKind
, Window
*pWinParent
)
1054 : AnyWidget( pWidget
, aPropName
, aPropKind
), layout::ListBox( pWinParent
, WB_DROPDOWN
)
1056 SetSelectHdl( LINK( this, AnyWidget
, ApplyPropertyHdl
) );
1059 virtual layout::Window
*getWindow()
1064 SelectEntryPos( sal::static_int_cast
< USHORT
>( getValue().toInt32() ) );
1068 virtual void store()
1070 save( uno::makeAny( (short) GetSelectEntryPos() ) );
1074 struct AnyAlign
: public AnyListBox
1076 AnyAlign( Widget
*pWidget
, rtl::OUString aPropName
,
1077 Widget::PropertyKind aPropKind
, Window
*pWinParent
)
1078 : AnyListBox( pWidget
, aPropName
, aPropKind
, pWinParent
)
1080 InsertEntry( XubString::CreateFromAscii( "Left" ) );
1081 InsertEntry( XubString::CreateFromAscii( "Center" ) );
1082 InsertEntry( XubString::CreateFromAscii( "Right" ) );
1087 /* AnyListBox and AnyComboBox different in that a ComboBox allows the user
1088 to add other options, operating in strings, instead of constants.
1089 (its more like a suggestive AnyEdit) */
1090 struct AnyComboBox
: public AnyWidget
, layout::ComboBox
1092 AnyComboBox( Widget
*pWidget
, rtl::OUString aPropName
,
1093 Widget::PropertyKind aPropKind
, Window
*pWinParent
)
1094 : AnyWidget( pWidget
, aPropName
, aPropKind
), layout::ComboBox( pWinParent
, WB_DROPDOWN
)
1096 SetModifyHdl( LINK( this, AnyComboBox
, ApplyPropertyHdl
) );
1099 virtual layout::Window
*getWindow()
1104 SetText( getValue() );
1108 virtual void store()
1110 save( uno::makeAny( (rtl::OUString
) GetText() ) );
1114 struct AnyFontStyle
: public AnyComboBox
1116 AnyFontStyle( Widget
*pWidget
, rtl::OUString aPropName
,
1117 Widget::PropertyKind aPropKind
, Window
*pWinParent
)
1118 : AnyComboBox( pWidget
, aPropName
, aPropKind
, pWinParent
)
1120 InsertEntry( XubString::CreateFromAscii( "Bold" ) );
1121 InsertEntry( XubString::CreateFromAscii( "Italic" ) );
1122 InsertEntry( XubString::CreateFromAscii( "Bold Italic" ) );
1123 InsertEntry( XubString::CreateFromAscii( "Fett" ) );
1128 layout::FixedText
*mpLabel
;
1129 layout::CheckBox
*mpFlag
;
1133 PropertyEntry( layout::Window
*pWinParent
, AnyWidget
*pAnyWidget
)
1135 mpLabel
= new layout::FixedText( pWinParent
);
1137 // append ':' to aPropName
1138 rtl::OUStringBuffer
buf( pAnyWidget
->maPropName
);
1139 buf
.append( sal_Unicode (':') );
1140 mpLabel
->SetText( buf
.makeStringAndClear() );
1142 mpValue
= pAnyWidget
;
1143 mpFlag
= new layout::CheckBox( pWinParent
);
1144 mpFlag
->SetToggleHdl( LINK( mpValue
, AnyWidget
, FlagToggledHdl
) );
1145 mpValue
->mpFlag
= mpFlag
;
1151 fprintf(stderr
, "REMOVING label, flag and value\n");
1158 // Use this factory rather than the constructor -- check for NULL
1159 static PropertyEntry
*construct( Widget
*pWidget
, rtl::OUString aPropName
,
1160 Widget::PropertyKind aPropKind
, sal_uInt16 nType
,
1161 layout::Window
*pWinParent
)
1163 AnyWidget
*pAnyWidget
;
1165 case uno::TypeClass_STRING
:
1166 if ( aPropName
.compareToAscii( "FontStyleName" ) == 0 )
1168 pAnyWidget
= new AnyFontStyle( pWidget
, aPropName
, aPropKind
, pWinParent
);
1171 pAnyWidget
= new AnyEdit( pWidget
, aPropName
, aPropKind
, pWinParent
);
1173 case uno::TypeClass_SHORT
:
1174 if ( aPropName
.compareToAscii( "Align" ) == 0 )
1176 pAnyWidget
= new AnyAlign( pWidget
, aPropName
, aPropKind
, pWinParent
);
1179 // otherwise, treat as any other number...
1180 case uno::TypeClass_LONG
:
1181 case uno::TypeClass_UNSIGNED_LONG
:
1182 pAnyWidget
= new AnyInteger( pWidget
, aPropName
, aPropKind
, pWinParent
);
1184 case uno::TypeClass_FLOAT
:
1185 case uno::TypeClass_DOUBLE
:
1186 pAnyWidget
= new AnyFloat( pWidget
, aPropName
, aPropKind
, pWinParent
);
1188 case uno::TypeClass_BOOLEAN
:
1189 pAnyWidget
= new AnyCheckBox( pWidget
, aPropName
, aPropKind
, pWinParent
);
1194 return new PropertyEntry( pWinParent
, pAnyWidget
);
1198 layout::Window
*mpParentWindow
;
1200 std::list
< PropertyEntry
* > maPropertiesList
;
1201 layout::FixedLine
*mpSeparator
;
1203 // some properties are obscure, or simply don't make sense in this
1204 // context. Let's just ignore them.
1205 // Maybe we could offer them in an expander or something...
1206 static bool toIgnore( rtl::OUString prop
)
1208 // binary search -- keep the list sorted alphabetically
1209 static char const *toIgnoreList
[] = {
1210 "DefaultControl", "FocusOnClick", "FontCharWidth", "FontCharset",
1211 "FontEmphasisMark", "FontFamily", "FontHeight", "FontKerning", "FontName",
1212 "FontOrientation", "FontPitch", "FontRelief", "FontSlant", "FontStrikeout",
1213 "FontType", "FontWordLineMode", "HelpText", "HelpURL", "MultiLine",
1214 "Printable", "Repeat", "RepeatDelay", "Tabstop"
1218 // checks list sanity -- enable this when you add some entries...
1219 for ( unsigned int i
= 1; i
< sizeof( toIgnoreList
)/sizeof( char * ); i
++ )
1221 if ( strcmp(toIgnoreList
[i
-1], toIgnoreList
[i
]) >= 0 )
1223 printf("ignore list not ordered properly: "
1224 "'%s' should come before '%s'\n",
1225 toIgnoreList
[i
], toIgnoreList
[i
-1]);
1231 int min
= 0, max
= sizeof( toIgnoreList
)/sizeof( char * ) - 1, mid
, cmp
;
1233 mid
= min
+ (max
- min
)/2;
1234 cmp
= prop
.compareToAscii( toIgnoreList
[ mid
] );
1241 } while ( min
<= max
);
1246 PropertiesList( layout::Dialog
*dialog
)
1247 : layout::Table( dialog
, "properties-box" )
1248 , mpParentWindow( dialog
), mpSeparator( 0 )
1258 // auxiliary, add properties from the peer to the list
1259 void addProperties( Widget
*pWidget
, Widget::PropertyKind rKind
)
1261 Widget::PropertyIterator
it( pWidget
, rKind
);
1262 while ( it
.hasNext() )
1264 beans::Property prop
= it
.next();
1265 rtl::OUString
name( prop
.Name
);
1266 if ( toIgnore( name
) )
1268 sal_uInt16 type
= static_cast< sal_uInt16
>( prop
.Type
.getTypeClass() );
1270 PropertyEntry
*propEntry
= PropertyEntry::construct(
1271 pWidget
, name
, rKind
, type
, mpParentWindow
);
1275 Add( propEntry
->mpLabel
, false, false );
1277 // HACK: one of these will return Null...
1278 Add( propEntry
->mpValue
->getWindow(), true, false );
1279 Add( propEntry
->mpValue
->getContainer(), true, false );
1281 Add( propEntry
->mpFlag
, false, false );
1282 maPropertiesList
.push_back( propEntry
);
1288 void selectedWidget( Widget
*pWidget
)
1295 addProperties( pWidget
, Widget::CONTAINER_PROPERTY
);
1297 mpSeparator
= new layout::FixedLine( mpParentWindow
);
1298 // TODO: we may want to have to separate list widgets here...
1299 Add( mpSeparator
, false, false, 3, 1 );
1301 addProperties( pWidget
, Widget::WINDOW_PROPERTY
);
1311 for ( std::list
< PropertyEntry
* >::iterator it
= maPropertiesList
.begin();
1312 it
!= maPropertiesList
.end(); it
++)
1314 maPropertiesList
.clear();
1321 IMPL_LINK( PropertiesList::PropertyEntry::AnyWidget
, ApplyPropertyHdl
, layout::Window
*, pWin
)
1328 IMPL_LINK( PropertiesList::PropertyEntry::AnyWidget
, FlagToggledHdl
, layout::CheckBox
*, pCheck
)
1331 fprintf(stderr
, "Property flag pressed -- is: %d\n", pCheck
->IsChecked());
1333 if ( !mbBlockFlagCallback
)
1335 bool checked
= pCheck
->IsChecked();
1336 if ( !checked
) // revert
1339 fprintf(stderr
, "revert\n");
1346 fprintf(stderr
, "user can't dirty the flag!\n");
1348 // User can't flag the property as dirty
1349 // Actually, we may want to allow the designer to force a property to be stored.
1350 // Could be useful when the default value of some new property wasn't yet decided...
1351 CheckFlag( false, true );
1356 fprintf(stderr
, "Property flag pressed -- BLOCKED\n");
1361 IMPL_LINK( PropertiesList::PropertyEntry::AnyEdit
, ExpandEditHdl
, layout::PushButton
*, pBtn
)
1363 setAsMultiLine( pBtn
->IsChecked() );
1367 //** SortListBox auxiliary widget
1370 { // For a manual sort ListBox; asks for a ListBox and Up/Down/Remove
1372 DECL_LINK( ItemSelectedHdl
, layout::ListBox
* );
1373 DECL_LINK( UpPressedHdl
, layout::Button
* );
1374 DECL_LINK( DownPressedHdl
, layout::Button
* );
1375 DECL_LINK( RemovePressedHdl
, layout::Button
* );
1376 layout::PushButton
*mpUpButton
, *mpDownButton
, *mpRemoveButton
;
1379 layout::ListBox
*mpListBox
;
1381 virtual void upPressed( USHORT nPos
)
1383 XubString str
= mpListBox
->GetSelectEntry();
1384 mpListBox
->RemoveEntry( nPos
);
1385 nPos
= mpListBox
->InsertEntry( str
, nPos
-1 );
1386 mpListBox
->SelectEntryPos( nPos
);
1389 virtual void downPressed( USHORT nPos
)
1391 XubString str
= mpListBox
->GetSelectEntry();
1392 mpListBox
->RemoveEntry( nPos
);
1393 nPos
= mpListBox
->InsertEntry( str
, nPos
+1 );
1394 mpListBox
->SelectEntryPos( nPos
);
1397 virtual void removePressed( USHORT nPos
)
1399 mpListBox
->RemoveEntry( nPos
);
1402 virtual void itemSelected( USHORT nPos
)
1404 // if we had some XLayoutContainer::canAdd() or maxChildren() function
1405 // we could make a function to check if we can move selected and enable/
1406 // /disable the move buttons as appropriate
1408 if ( nPos
== LISTBOX_ENTRY_NOTFOUND
)
1410 mpUpButton
->Disable();
1411 mpDownButton
->Disable();
1412 mpRemoveButton
->Disable();
1416 mpUpButton
->Enable();
1417 mpDownButton
->Enable();
1418 mpRemoveButton
->Enable();
1423 SortListBox( layout::ListBox
*pListBox
, layout::PushButton
*pUpButton
, layout::PushButton
*pDownButton
,
1424 layout::PushButton
*pRemoveButton
)
1425 : mpUpButton( pUpButton
), mpDownButton( pDownButton
), mpRemoveButton( pRemoveButton
),
1426 mpListBox( pListBox
)
1428 mpListBox
->SetSelectHdl( LINK( this, SortListBox
, ItemSelectedHdl
) );
1430 mpUpButton
->SetModeImage( layout::Image ( "res/commandimagelist/lc_moveup.png" ) );
1431 mpUpButton
->SetImageAlign( IMAGEALIGN_LEFT
);
1432 mpUpButton
->SetClickHdl( LINK( this, SortListBox
, UpPressedHdl
) );
1434 mpDownButton
->SetModeImage( layout::Image ( "res/commandimagelist/lc_movedown.png" ) );
1435 mpDownButton
->SetImageAlign( IMAGEALIGN_LEFT
);
1436 mpDownButton
->SetClickHdl( LINK( this, SortListBox
, DownPressedHdl
) );
1438 // "res/commandimagelist/lch_delete.png", "res/commandimagelist/lc_delete.png"
1439 mpRemoveButton
->SetModeImage( layout::Image ( "res/commandimagelist/sc_closedoc.png" ) );
1440 mpRemoveButton
->SetImageAlign( IMAGEALIGN_LEFT
);
1441 mpRemoveButton
->SetClickHdl( LINK( this, SortListBox
, RemovePressedHdl
) );
1443 // fire an un-select event
1444 itemSelected( LISTBOX_ENTRY_NOTFOUND
);
1447 virtual ~SortListBox();
1450 SortListBox::~SortListBox()
1454 delete mpDownButton
;
1455 delete mpRemoveButton
;
1458 IMPL_LINK( SortListBox
, UpPressedHdl
, layout::Button
*, pBtn
)
1461 USHORT pos
= mpListBox
->GetSelectEntryPos();
1462 if ( pos
> 0 && pos
!= LISTBOX_ENTRY_NOTFOUND
)
1467 IMPL_LINK( SortListBox
, DownPressedHdl
, layout::Button
*, pBtn
)
1470 USHORT pos
= mpListBox
->GetSelectEntryPos();
1471 if ( pos
< mpListBox
->GetEntryCount() && pos
!= LISTBOX_ENTRY_NOTFOUND
)
1476 IMPL_LINK( SortListBox
, RemovePressedHdl
, layout::Button
*, pBtn
)
1479 USHORT pos
= mpListBox
->GetSelectEntryPos();
1480 if ( pos
!= LISTBOX_ENTRY_NOTFOUND
)
1481 removePressed( pos
);
1485 IMPL_LINK( SortListBox
, ItemSelectedHdl
, layout::ListBox
*, pList
)
1488 USHORT pos
= mpListBox
->GetSelectEntryPos();
1489 itemSelected( pos
);
1493 //** LayoutTree widget
1495 class LayoutTree
: public SortListBox
1500 virtual void widgetSelected( Widget
*pWidget
) = 0;
1504 Listener
*mpListener
;
1507 Widget
*mpRootWidget
;
1509 LayoutTree( layout::Dialog
*dialog
)
1510 : SortListBox( new layout::ListBox( dialog
, "layout-tree" ),
1511 new layout::PushButton( dialog
, "layout-up-button" ),
1512 new layout::PushButton( dialog
, "layout-down-button" ),
1513 new layout::PushButton( dialog
, "layout-remove-button" ) )
1515 layout::PeerHandle handle
= dialog
->GetPeerHandle( "preview-box" );
1516 uno::Reference
< awt::XLayoutConstrains
> xWidget( handle
, uno::UNO_QUERY
);
1517 mpRootWidget
= new Widget( xWidget
, "root" );
1520 virtual ~LayoutTree();
1522 Widget
*getWidget( int nPos
)
1524 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
1525 return FlatLayout::get( mpRootWidget
, nPos
);
1529 Widget
*getSelectedWidget()
1531 Widget
*pWidget
= getWidget( mpListBox
->GetSelectEntryPos() );
1532 if ( !pWidget
) // return root, if none selected
1533 pWidget
= mpRootWidget
;
1537 void selectWidget( Widget
*pWidget
)
1539 int pos
= FlatLayout::get( mpRootWidget
, pWidget
);
1541 // if asked to select hidden root, select visible root
1543 mpListBox
->SelectEntryPos( sal::static_int_cast
< USHORT
>( pos
) );
1550 // pads a string with whitespaces
1551 static rtl::OUString
padString( rtl::OUString name
, int depth
)
1553 rtl::OStringBuffer
aBuf( depth
* 4 + name
.getLength() + 2 );
1554 for (int i
= 0; i
< depth
; i
++)
1556 aBuf
.append( rtl::OUStringToOString( name
, RTL_TEXTENCODING_ASCII_US
) );
1557 return rtl::OUString( aBuf
.getStr(), aBuf
.getLength(),
1558 RTL_TEXTENCODING_UTF8
);
1563 for ( Widget
*i
= FlatLayout::next( mpRootWidget
); i
; i
= FlatLayout::next( i
) )
1564 mpListBox
->InsertEntry( inner::padString( i
->getLabel(), i
->getDepth()-1 ) );
1566 // any selection, no longer is. ListBox doesn't fire the event on this case;
1568 itemSelected( LISTBOX_ENTRY_NOTFOUND
);
1571 void setListener( Listener
*pListener
)
1572 { mpListener
= pListener
; }
1574 // print in XML format...
1576 static rtl::OUString
toXMLNaming (const rtl::OUString
&string
)
1578 rtl::OUStringBuffer
buffer (string
.getLength());
1579 sal_Unicode
*str
= string
.pData
->buffer
;
1580 for (int i
= 0; i
< string
.getLength(); i
++) {
1581 if ( str
[i
] >= 'A' && str
[i
] <= 'Z' )
1584 buffer
.append ((sal_Unicode
) '-');
1585 buffer
.append ((sal_Unicode
) (str
[i
] - 'A' + 'a'));
1588 buffer
.append ((sal_Unicode
) str
[i
]);
1591 return buffer
.makeStringAndClear();
1596 printf("\t\tExport:\n");
1597 printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1598 "<dialog xmlns=\"http://openoffice.org/2007/layout\"\n"
1599 " xmlns:cnt=\"http://openoffice.org/2007/layout/container\"\n"
1600 " id=\"dialog\" title=\"Unnamed\" sizeable=\"true\" >\n");
1602 for ( Widget
*i
= FlatLayout::next( mpRootWidget
); i
; i
= FlatLayout::next( i
) )
1604 for ( int d
= i
->getDepth(); d
> 0; d
-- )
1606 printf("<%s ", OUSTRING_CSTR( i
->getUnoName() ) );
1608 for ( int kind
= 0; kind
< 2; kind
++ )
1610 Widget::PropertyKind wKind
= kind
== 0 ? Widget::WINDOW_PROPERTY
1611 : Widget::CONTAINER_PROPERTY
;
1612 Widget::PropertyIterator
it( i
, wKind
);
1613 while ( it
.hasNext() )
1615 beans::Property prop
= it
.next();
1616 if ( !i
->isPropertyTouched( prop
.Name
, wKind
) )
1619 rtl::OUString value
= i
->getProperty( prop
.Name
, wKind
);
1620 if ( prop
.Type
.getTypeClass() == uno::TypeClass_BOOLEAN
)
1622 if ( value
.compareToAscii( "0" ) )
1623 value
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("false") );
1625 value
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("true") );
1628 if ( value
.getLength() > 0 )
1629 printf("%s%s=\"%s\" ",
1630 kind
== 0 ? "" : "cnt:",
1631 OUSTRING_CSTR( toXMLNaming( prop
.Name
) ), OUSTRING_CSTR( value
)
1638 printf("</dialog>\n");
1642 virtual void upPressed( USHORT nPos
)
1644 Widget
*pWidget
= getWidget( nPos
);
1645 if ( FlatLayout::moveWidget( pWidget
, true ) )
1647 selectWidget( pWidget
);
1650 virtual void downPressed( USHORT nPos
)
1652 Widget
*pWidget
= getWidget( nPos
);
1653 if ( FlatLayout::moveWidget( pWidget
, false ) )
1655 selectWidget( pWidget
);
1658 virtual void removePressed( USHORT nPos
)
1660 Widget
*pWidget
= getWidget( nPos
);
1663 pWidget
->up()->removeChild( pWidget
);
1669 virtual void itemSelected( USHORT nPos
)
1671 mpListener
->widgetSelected( getWidget( nPos
) );
1672 SortListBox::itemSelected( nPos
);
1676 LayoutTree::~LayoutTree()
1678 delete mpRootWidget
;
1683 class EditorImpl
: public LayoutTree::Listener
1685 void createWidget( const char *unoName
);
1687 PropertiesList
*mpPropertiesList
;
1688 LayoutTree
*mpLayoutTree
;
1690 layout::PushButton
*pImportButton
, *pExportButton
;
1692 FileDialog
*pImportDialog
;
1694 DECL_LINK( ImportButtonHdl
, layout::PushButton
* );
1695 DECL_LINK( ExportButtonHdl
, layout::PushButton
* );
1697 DECL_LINK( ImportDialogHdl
, FileDialog
* );
1701 uno::Reference
< lang::XMultiServiceFactory
> mxFactory
;
1702 uno::Reference
< awt::XToolkit
> mxToolkit
;
1703 uno::Reference
< awt::XWindow
> mxToplevel
;
1705 virtual void widgetSelected( Widget
*pWidget
);
1706 DECL_LINK( CreateWidgetHdl
, layout::Button
* );
1708 std::list
< layout::PushButton
*> maCreateButtons
;
1712 EditorImpl( layout::Dialog
*dialog
,
1713 // we should probable open this channel (or whatever its called) ourselves
1714 uno::Reference
< lang::XMultiServiceFactory
> xMSF
);
1715 virtual ~EditorImpl();
1717 void loadFile( const rtl::OUString
&aTestFile
);
1720 EditorImpl::EditorImpl( layout::Dialog
*dialog
,
1721 uno::Reference
< lang::XMultiServiceFactory
> xFactory
)
1722 : mxFactory( xFactory
)
1723 , mxToplevel( dialog
->GetPeerHandle( "dialog" ), uno::UNO_QUERY
)
1724 // FIXME: any of these should work
1725 //dialog->getContext()->getRoot(), uno::UNO_QUERY )
1726 // dialog->GetPeer(), uno::UNO_QUERY )
1729 fprintf (stderr
, "EditorImpl()\n");
1732 mxToolkit
= uno::Reference
< awt::XToolkit
>(
1733 mxFactory
->createInstance(
1734 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.Toolkit" ) ) ),
1736 assert( mxToolkit
.is() );
1740 fprintf (stderr
, "custom widgets\n");
1742 mpPropertiesList
= new PropertiesList( dialog
);
1744 mpLayoutTree
= new LayoutTree( dialog
);
1745 mpLayoutTree
->setListener( this );
1747 /* if ( xImport.is() )
1748 mpLayoutTree->getWidget( -1 )->addChild( new Widget( xImport, "import" ) );*/
1751 layout::Container
aWidgets( dialog
, "create-widget" );
1752 layout::Container
aContainers( dialog
, "create-container" );
1753 for ( int i
= 0; i
< WIDGETS_SPECS_LEN
; i
++ )
1755 layout::PushButton
*pBtn
= new layout::PushButton( (layout::Window
*) dialog
);
1756 pBtn
->SetText( rtl::OUString::createFromAscii( WIDGETS_SPECS
[ i
].pLabel
) );
1757 pBtn
->SetClickHdl( LINK( this, EditorImpl
, CreateWidgetHdl
) );
1758 if ( WIDGETS_SPECS
[ i
].pIconName
!= NULL
)
1760 rtl::OString
aPath ("res/commandimagelist/");
1761 aPath
+= WIDGETS_SPECS
[ i
].pIconName
;
1762 layout::Image
aImg( aPath
);
1763 pBtn
->SetModeImage( aImg
);
1764 pBtn
->SetImageAlign( IMAGEALIGN_LEFT
);
1767 maCreateButtons
.push_back( pBtn
);
1768 layout::Container
*pBox
= WIDGETS_SPECS
[ i
].bIsContainer
? &aContainers
: &aWidgets
;
1773 fprintf(stderr
,"creating file dialog\n");
1774 pImportDialog
= new FileDialog( NULL
/*(layout::Window *) dialog*/, 0 );
1775 fprintf(stderr
,"connecting it\n");
1776 pImportDialog
->SetFileSelectHdl( LINK( this, EditorImpl
, ImportDialogHdl
) );
1777 fprintf(stderr
,"done file dialog\n");
1780 /* pImportButton = new layout::PushButton( dialog, "import-button" );
1781 pImportButton->SetClickHdl( LINK( this, EditorImpl, ImportButtonHdl ) );*/
1782 pExportButton
= new layout::PushButton( dialog
, "export-button" );
1783 pExportButton
->SetClickHdl( LINK( this, EditorImpl
, ExportButtonHdl
) );
1786 EditorImpl::~EditorImpl()
1788 delete mpPropertiesList
;
1789 delete mpLayoutTree
;
1790 for ( std::list
< layout::PushButton
* >::const_iterator i
= maCreateButtons
.begin();
1791 i
!= maCreateButtons
.end(); i
++)
1793 delete pImportButton
;
1794 delete pExportButton
;
1796 delete pImportDialog
;
1800 void EditorImpl::loadFile( const rtl::OUString
&aTestFile
)
1802 fprintf( stderr
, "TEST: layout instance\n" );
1803 uno::Reference
< awt::XLayoutRoot
> xRoot
1804 ( new EditorRoot( mxFactory
, mpLayoutTree
->mpRootWidget
) );
1807 mxMSF->createInstance
1808 ( ::rtl::OUString::createFromAscii( "com.sun.star.awt.Layout" ) ),
1813 throw uno::RuntimeException(
1814 OUString( RTL_CONSTASCII_USTRINGPARAM("could not create awt Layout component!") ),
1815 uno::Reference
< uno::XInterface
>() );
1819 fprintf( stderr
, "TEST: initing root\n" );
1822 uno::Reference
< lang::XInitialization
> xInit( xRoot
, uno::UNO_QUERY
);
1825 throw uno::RuntimeException(
1826 OUString( RTL_CONSTASCII_USTRINGPARAM("Layout has no XInitialization!") ),
1827 uno::Reference
< uno::XInterface
>() );
1831 fprintf( stderr
, "TEST: running parser\n" );
1833 uno::Sequence
< uno::Any
> aParams( 1 );
1834 aParams
[0] <<= aTestFile
;
1836 fprintf( stderr
, "TEST: do it\n" );
1838 xInit
->initialize( aParams
);
1840 fprintf( stderr
, "TEST: file loaded\n" );
1843 mpLayoutTree
->rebuild();
1846 void EditorImpl::createWidget( const char *name
)
1848 Widget
*pWidget
= mpLayoutTree
->getSelectedWidget();
1850 Widget
*pChild
= new Widget( rtl::OUString(), mxToolkit
, uno::Reference
< awt::XLayoutContainer
>( mxToplevel
, uno::UNO_QUERY
), rtl::OUString::createFromAscii( name
), awt::WindowAttribute::SHOW
);
1851 if ( !pWidget
->addChild( pChild
) )
1854 // we may want to popup an error message
1858 mpLayoutTree
->rebuild();
1859 mpLayoutTree
->selectWidget( pWidget
);
1863 void EditorImpl::widgetSelected( Widget
*pWidget
)
1865 // we know can't add widget to a non-container, so let's disable the create
1866 // buttons then. Would be nice to have a method to check if a container is
1868 if ( !pWidget
|| pWidget
->isContainer() )
1870 for ( std::list
< layout::PushButton
*>::const_iterator it
= maCreateButtons
.begin();
1871 it
!= maCreateButtons
.end(); it
++)
1876 for ( std::list
< layout::PushButton
*>::const_iterator it
= maCreateButtons
.begin();
1877 it
!= maCreateButtons
.end(); it
++)
1881 mpPropertiesList
->selectedWidget( pWidget
);
1884 IMPL_LINK( EditorImpl
, CreateWidgetHdl
, layout::Button
*, pBtn
)
1887 for ( std::list
< layout::PushButton
*>::const_iterator it
= maCreateButtons
.begin();
1888 it
!= maCreateButtons
.end(); it
++, i
++ )
1893 assert( i
< WIDGETS_SPECS_LEN
);
1894 createWidget( WIDGETS_SPECS
[i
].pName
);
1898 IMPL_LINK( EditorImpl
, ImportButtonHdl
, layout::PushButton
*, pBtn
)
1902 fprintf(stderr
, "IMPORT!\n");
1905 pImportDialog
->Execute();
1912 IMPL_LINK( EditorImpl
, ImportDialogHdl
, FileDialog
*, pDialog
)
1914 UniString path
= pDialog
->GetPath();
1915 //fprintf(stderr, "Executing import dialog!\n");
1918 fprintf(stderr
, "got import file: %s\n",rtl::OUStringToOString( path
, RTL_TEXTENCODING_ASCII_US
).getStr() );
1925 IMPL_LINK( EditorImpl
, ExportButtonHdl
, layout::PushButton
*, pBtn
)
1928 mpLayoutTree
->print();
1932 //** Editor, the Dialog
1934 Editor::Editor( uno::Reference
< lang::XMultiServiceFactory
> xFactory
,
1935 rtl::OUString aFile
)
1936 : layout::Dialog( (Window
*) (NULL
), "editor.xml", "dialog" )
1937 , mpImpl( new EditorImpl( this, xFactory
) )
1939 if ( aFile
.getLength() )
1940 mpImpl
->loadFile( aFile
);