1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
43 #include <com/sun/star/awt/WindowAttribute.hpp>
44 #include <com/sun/star/awt/XLayoutConstrains.hpp>
45 #include <com/sun/star/awt/XLayoutContainer.hpp>
46 #include <com/sun/star/awt/XToolkit.hpp>
47 #include <com/sun/star/awt/XVclWindowPeer.hpp>
48 #include <com/sun/star/awt/XWindow.hpp>
49 #include <com/sun/star/awt/XWindowPeer.hpp>
50 #include <rtl/strbuf.hxx>
51 #include <rtl/ustrbuf.hxx>
52 #include <toolkit/helper/property.hxx>
53 #include <vcl/lstbox.h>
55 using namespace layout::css
;
62 #include <layout/core/helper.hxx>
63 #include <layout/core/root.hxx>
64 #include <layout/core/helper.hxx>
66 // TODO: automatically generated
68 const char *pLabel
, *pName
, *pIconName
;
70 static const WidgetSpec WIDGETS_SPECS
[] = {
71 { "Label", "fixedtext" , "sc_label.png", false },
72 { "Button", "pushbutton" , "sc_pushbutton.png", false },
73 { "Radio Button", "radiobutton" , "sc_radiobutton.png", false },
74 { "Check Box", "checkbox" , "sc_checkbox.png", false },
75 { "Line Edit", "edit" , "sc_edit.png", false },
76 { "Numeric Field", "numericfield", "sc_numericfield.png", false },
77 { "List Box ", "listbox" , NULL
, false },
79 { "Hor Box", "hbox" , NULL
, true },
80 { "Ver Box", "vbox" , NULL
, true },
81 { "Table", "table" , NULL
, true },
82 { "Alignment", "align" , NULL
, true },
83 { "Tab Control", "tabcontrol" , NULL
, true },
84 { "Hor Splitter", "hsplitter" , NULL
, true },
85 { "Ver Splitter", "vsplitter" , NULL
, true },
86 { "Scroller", "scroller" , NULL
, true },
88 const int WIDGETS_SPECS_LEN
= sizeof (WIDGETS_SPECS
) / sizeof (WidgetSpec
);
90 using namespace layout
;
91 using namespace layoutimpl
;
92 namespace css
= ::com::sun::star
;
94 static rtl::OUString
anyToString (uno::Any value
)
98 switch (value
.getValueTypeClass()) {
99 case uno::TypeClass_STRING
:
100 return value
.get
<rtl::OUString
>();
101 case uno::TypeClass_CONSTANT
:
102 return rtl::OUString::valueOf (value
.get
<sal_Int32
>());
103 case uno::TypeClass_LONG
:
104 return rtl::OUString::valueOf (value
.get
<sal_Int64
>());
105 case uno::TypeClass_SHORT
:
106 // FIXME: seems broken
107 return rtl::OUString::valueOf ((sal_Int32
) value
.get
<short>());
109 case uno::TypeClass_FLOAT
:
110 return rtl::OUString::valueOf (value
.get
<float>());
111 case uno::TypeClass_DOUBLE
:
112 return rtl::OUString::valueOf (value
.get
<double>());
114 case uno::TypeClass_BOOLEAN
:
116 bool val
= value
.get
<sal_Bool
>();
117 return rtl::OUString( val
? "1" : "0", 1, RTL_TEXTENCODING_ASCII_US
);
119 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
121 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) );*/
128 return rtl::OUString();
131 static inline long anyToNatural (uno::Any value
)
132 { return sal::static_int_cast
<long>(anyToString( value
).toInt64()); }
133 static inline double anyToDecimal (uno::Any value
)
134 { return anyToString( value
).toDouble(); }
136 /* XLayoutContainer/XLayoutConstrains are a bit of a hasle to work with.
138 class Widget
: public layoutimpl::LayoutWidget
140 friend class EditorRoot
;
143 std::vector
< Widget
*> maChildren
;
147 rtl::OUString mrLabel
, mrUnoName
;
149 // TODO: store original properties. And some property handling methods.
151 layoutimpl::PropList maOriProps
, maOriChildProps
;
155 // to be used to wrap the root
156 Widget( uno::Reference
< awt::XLayoutConstrains
> xImport
, const char *label
)
157 : mpParent( 0 ), mbForeign( true )
160 mxContainer
= uno::Reference
< awt::XLayoutContainer
>( mxWidget
, uno::UNO_QUERY
);
162 mrLabel
= rtl::OUString( label
, strlen( label
), RTL_TEXTENCODING_UTF8
);
165 // FIXME: this code is meant to import a XML file. Just use the importer,
166 // then pass the root widget. But information like the ID string is lost.
167 // So, this needs to be more closely tight to the importer.
168 uno::Sequence
< uno::Reference
< awt::XLayoutConstrains
> > aChildren
;
169 for ( int i
= 0; i
< aChildren
.getLength(); i
++ )
171 Widget
*pChild
= new Widget( aChildren
[ i
], "---" );
172 maChildren
.push_back( pChild
);
173 pChild
->mpParent
= this;
178 Widget( rtl::OUString id
, uno::Reference
< awt::XToolkit
> xToolkit
,
179 uno::Reference
< awt::XLayoutContainer
> xParent
,
180 rtl::OUString unoName
, long nAttrbs
)
181 : mpParent( 0 ), mbForeign( false ), mrId( id
),
182 mnOriAttrbs( nAttrbs
)
184 while ( xParent
.is() && !uno::Reference
< awt::XWindow
>( xParent
, uno::UNO_QUERY
).is() )
186 uno::Reference
< awt::XLayoutContainer
> xContainer( xParent
, uno::UNO_QUERY
);
187 OSL_ASSERT( xContainer
.is() );
188 xParent
= uno::Reference
< awt::XLayoutContainer
>( xContainer
->getParent(), uno::UNO_QUERY
);
191 mxWidget
= WidgetFactory::createWidget( xToolkit
, xParent
, unoName
, nAttrbs
);
192 OSL_ASSERT( mxWidget
.is() );
193 mxContainer
= uno::Reference
< awt::XLayoutContainer
>( mxWidget
, uno::UNO_QUERY
);
195 mrLabel
= mrUnoName
= unoName
;
196 // try to get a nicer label for the widget
197 for ( int i
= 0; i
< WIDGETS_SPECS_LEN
; i
++ )
198 if ( unoName
.equalsAscii( WIDGETS_SPECS
[ i
].pName
) )
200 const char *label
= WIDGETS_SPECS
[ i
].pLabel
;
201 mrLabel
= rtl::OUString( label
, strlen( label
), RTL_TEXTENCODING_UTF8
);
205 // set default Text property
206 // TODO: disable editing of text fields, check boxes selected, etc...
208 uno::Reference
< awt::XVclWindowPeer
> xVclPeer( mxWidget
, uno::UNO_QUERY
)
209 if ( xVclPeer
.is() ) // XVclWindowPeer ignores missing / incorrect properties
211 //FIXME: it looks odd on widgets like NumericField seeing text which is deleted
212 // when you interact with it... We can avoid it for those widgets, by doing a getProp
213 // of "Text" and check if it is empty or not.
215 xVclPeer
->setProperty( rtl::OUString::createFromAscii( "Text" ),
216 uno::makeAny( rtl::OUString::createFromAscii( "new widget" ) ) );
219 // store original properties
221 PropertyIterator
it( this, WINDOW_PROPERTY
);
222 while ( it
.hasNext() )
224 beans::Property prop
= it
.next();
225 rtl::OUString
name( prop
.Name
);
226 rtl::OUString
value( getProperty( name
, WINDOW_PROPERTY
) );
228 fprintf(stderr
, "original property: %s = %s\n", OUSTRING_CSTR(name
), OUSTRING_CSTR(value
));
230 std::pair
< rtl::OUString
, rtl::OUString
> pair( name
, value
);
231 maOriProps
.push_back( pair
);
239 for ( std::vector
< Widget
*>::const_iterator it
= maChildren
.begin();
240 it
!= maChildren
.end(); it
++ )
244 uno::Reference
< lang::XComponent
> xComp( mxWidget
, uno::UNO_QUERY
);
246 // some widgets, like our containers, don't implement this interface...
251 uno::Reference
< awt::XLayoutConstrains
> impl()
257 virtual bool addChild( LayoutWidget
*pChild
)
259 return addChild( static_cast< Widget
* >( pChild
) );
262 virtual void setProperties( const PropList
&rProps
)
264 // maOriProps = rProps;
265 LayoutWidget::setProperties( rProps
);
268 virtual void setChildProperties( LayoutWidget
*pChild
, const PropList
&rProps
)
270 maOriChildProps
= rProps
;
271 LayoutWidget::setChildProperties( pChild
, rProps
);
282 if ( maChildren
.empty() )
284 return maChildren
.front();
291 int pos
= mpParent
->getChildPos( this );
292 return mpParent
->getChild( pos
+1 );
301 int pos
= mpParent
->getChildPos( this );
302 return mpParent
->getChild( pos
-1 );
308 bool addChild( Widget
*pChild
, int pos
= 0xffff )
310 if ( !mxContainer
.is() )
313 uno::Sequence
< uno::Reference
< awt::XLayoutConstrains
> > aChildren
;
314 aChildren
= mxContainer
->getChildren();
315 int nChildrenLen
= aChildren
.getLength();
317 // ugly, but let's check if the container is next to full...
319 mxContainer
->addChild( pChild
->mxWidget
);
321 catch( awt::MaxChildrenException ex
) {
325 if ( pos
< nChildrenLen
)
326 { // if its on the middle, we need to make space for it
327 mxContainer
->removeChild( pChild
->mxWidget
);
328 for ( int i
= pos
; i
< nChildrenLen
; i
++ )
329 mxContainer
->removeChild( aChildren
[ i
] );
330 mxContainer
->addChild( pChild
->mxWidget
);
331 for ( int i
= pos
; i
< nChildrenLen
; i
++ )
332 mxContainer
->addChild( aChildren
[ i
] );
333 maChildren
.insert( maChildren
.begin()+pos
, pChild
);
336 maChildren
.push_back( pChild
);
338 OSL_ASSERT( pChild
->mpParent
== NULL
);
339 pChild
->mpParent
= this;
341 // store container props
343 pChild
->maOriChildProps
.clear();
344 PropertyIterator
it( pChild
, CONTAINER_PROPERTY
);
345 while ( it
.hasNext() )
347 beans::Property prop
= it
.next();
348 rtl::OUString
name( prop
.Name
);
350 rtl::OUString
value( pChild
->getProperty( name
, CONTAINER_PROPERTY
) );
351 std::pair
< rtl::OUString
, rtl::OUString
> pair( name
, value
);
352 pChild
->maOriChildProps
.push_back( pair
);
353 } catch ( beans::UnknownPropertyException
&rEx
) {
354 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",
355 rtl::OUStringToOString (rEx
.Message
, RTL_TEXTENCODING_UTF8
).getStr());
363 bool removeChild( Widget
*pChild
)
365 if ( !mxContainer
.is() || pChild
->mpParent
!= this )
368 mxContainer
->removeChild( pChild
->mxWidget
);
370 unsigned int pos
= getChildPos( pChild
);
371 if ( pos
< maChildren
.size() )
372 maChildren
.erase( maChildren
.begin()+pos
);
373 pChild
->mpParent
= NULL
;
378 bool swapWithChild( Widget
*pChild
)
380 if ( !pChild
->isContainer() )
383 // remove all child's childrens, and try to add them here
384 removeChild( pChild
);
386 // keep a copy for failure
387 std::vector
< Widget
*> aChildren
= maChildren
;
388 std::vector
< Widget
*> aChildChildren
= pChild
->maChildren
;
390 for ( std::vector
< Widget
*>::const_iterator it
= aChildChildren
.begin();
391 it
!= aChildChildren
.end(); it
++ )
392 pChild
->removeChild( *it
);
394 for ( std::vector
< Widget
*>::const_iterator it
= aChildChildren
.begin();
395 it
!= aChildChildren
.end(); it
++ )
396 if ( !addChild( *it
) )
398 for ( std::vector
< Widget
*>::const_iterator jt
= aChildChildren
.begin();
401 for ( std::vector
< Widget
*>::const_iterator jt
= aChildChildren
.begin();
402 jt
!= aChildChildren
.end(); jt
++ )
403 pChild
->addChild( *jt
);
407 Widget
*pParent
= up();
411 pParent
->removeChild( this );
412 pParent
->addChild( pChild
);
414 pChild
->addChild( this );
418 unsigned int getChildPos( Widget
*pChild
)
421 for ( std::vector
< Widget
*>::const_iterator it
= maChildren
.begin();
422 it
!= maChildren
.end(); it
++, i
++ )
428 Widget
*getChild( int pos
)
430 if ( pos
>= 0 && pos
< (signed) maChildren
.size() )
431 return *(maChildren
.begin() + pos
);
436 { return mxContainer
.is(); }
437 unsigned int getChildrenLen()
438 { return maChildren
.size(); }
440 rtl::OUString
getLabel() const
442 rtl::OUString
getUnoName() const
443 { return mrUnoName
; }
448 for ( Widget
*pWidget
= mpParent
; pWidget
; pWidget
= pWidget
->mpParent
)
454 WINDOW_PROPERTY
, CONTAINER_PROPERTY
, WINBITS_PROPERTY
457 static rtl::OUString
findProperty( const PropList
&props
, rtl::OUString propName
)
459 for ( PropList::const_iterator it
= props
.begin(); it
!= props
.end(); it
++ )
460 if ( it
->first
.equalsIgnoreAsciiCase( propName
) )
463 fprintf(stderr
, "Serious error: property '%s' not found\n", OUSTRING_CSTR(propName
));
465 return rtl::OUString();
468 rtl::OUString
getOriginalProperty( rtl::OUString rPropName
, PropertyKind rKind
)
470 rtl::OUString rValue
;
472 case WINDOW_PROPERTY
:
473 rValue
= findProperty( maOriProps
, rPropName
);
475 case CONTAINER_PROPERTY
:
476 rValue
= findProperty( maOriChildProps
, rPropName
);
478 case WINBITS_PROPERTY
:
486 rtl::OUString
getProperty( rtl::OUString rPropName
, PropertyKind rKind
)
488 rtl::OUString rValue
;
490 case WINDOW_PROPERTY
:
491 rValue
= anyToString( layoutimpl::prophlp::getProperty( mxWidget
, rPropName
) );
493 case CONTAINER_PROPERTY
:
495 rValue
= anyToString( layoutimpl::prophlp::getProperty(
496 mpParent
->mxContainer
->getChildProperties( mxWidget
), rPropName
) );
498 case WINBITS_PROPERTY
:
506 bool isPropertyTouched( rtl::OUString propName
, PropertyKind rKind
)
508 rtl::OUString oriValue
= getOriginalProperty( propName
, rKind
);
509 rtl::OUString newValue
= getProperty( propName
, rKind
);
510 bool isTouched
= oriValue
!= newValue
;
512 fprintf(stderr
, "is property '%s' touched? %s (%s vs %s)\n", OUSTRING_CSTR(propName
), isTouched
? "yes" : "no", OUSTRING_CSTR(oriValue
), OUSTRING_CSTR(newValue
));
517 using LayoutWidget::setProperty
;
519 void setProperty( rtl::OUString rPropName
, PropertyKind rKind
, uno::Any rValue
)
522 case WINDOW_PROPERTY
:
523 layoutimpl::prophlp::setProperty( mxWidget
, rPropName
, rValue
);
525 case CONTAINER_PROPERTY
:
527 layoutimpl::prophlp::setProperty(
528 mpParent
->mxContainer
->getChildProperties( mxWidget
), rPropName
, rValue
);
530 case WINBITS_PROPERTY
:
536 struct PropertyIterator
{
539 uno::Sequence
< beans::Property
> maProps
;
542 PropertyIterator( Widget
*pWidget
, PropertyKind rKind
)
543 : mrKind( rKind
), nPropIt( 0 )
547 case WINDOW_PROPERTY
:
548 if ( layoutimpl::prophlp::canHandleProps( pWidget
->mxWidget
) )
550 uno::Reference
< beans::XPropertySetInfo
> xInfo
551 = layoutimpl::prophlp::queryPropertyInfo( pWidget
->mxWidget
);
555 maProps
= xInfo
->getProperties();
558 case CONTAINER_PROPERTY
:
559 if ( pWidget
->mpParent
)
561 uno::Reference
< beans::XPropertySet
>xParentSet(
562 pWidget
->mpParent
->mxContainer
->getChildProperties( pWidget
->mxWidget
) );
563 if ( xParentSet
.is())
565 uno::Reference
< beans::XPropertySetInfo
> xInfo( xParentSet
->getPropertySetInfo() );
567 maProps
= xInfo
->getProperties();
571 case WINBITS_PROPERTY
:
579 return nPropIt
< maProps
.getLength();
582 beans::Property
next()
584 /* rtl::OUString propName, propValue;
585 propName = maProps[ nPropIt ];
586 propValue = getProperty( propName, mrKind, false);
588 return std::pair< rtl::OUString, rtl::OUString > propPair( propName, propValue );*/
589 return maProps
[ nPropIt
++ ];
594 class EditorRoot
: public layoutimpl::LayoutRoot
{
598 EditorRoot( const uno::Reference
< lang::XMultiServiceFactory
>& xFactory
,
600 : layoutimpl::LayoutRoot( xFactory
), mpParent( pParent
)
605 virtual layoutimpl::LayoutWidget
*create( rtl::OUString id
, const rtl::OUString unoName
,
606 long attrbs
, uno::Reference
< awt::XLayoutContainer
> xParent
)
608 if ( unoName
.compareToAscii( "dialog" ) == 0 )
611 // TODO: go through specs to map unoName to a more human-readable label
612 Widget
*pWidget
= new Widget( id
, mxToolkit
, xParent
, unoName
, attrbs
);
613 if ( !mxWindow
.is() )
614 mxWindow
= uno::Reference
< awt::XWindow
>( pWidget
->getPeer(), uno::UNO_QUERY
);
616 if ( pWidget
->mxContainer
.is() )
617 pWidget
->mxContainer
->setLayoutUnit( mpParent
->mxContainer
->getLayoutUnit() );
623 /* Working with the layout in 1D, as if it was a flat list. */
626 Widget
*next( Widget
*pWidget
)
629 pNext
= pWidget
->down();
630 if ( pNext
) return pNext
;
631 pNext
= pWidget
->next();
632 if ( pNext
) return pNext
;
633 for ( Widget
*pUp
= pWidget
->up(); pUp
!= NULL
; pUp
= pUp
->up() )
634 if ( (pNext
= pUp
->next()) != NULL
)
640 Widget *prev( Widget *pWidget )
643 pPrev = pWidget->prev();
645 return pWidget->up();
647 Widget *pBottom = pPrev->down();
650 while ( pBottom->down() || pBottom->next() )
652 for ( Widget *pNext = pBottom->next(); pNext; pNext = pNext->next() )
654 Widget *pDown = pBottom->down();
664 bool moveWidget( Widget
*pWidget
, bool up
/*or down*/ )
666 // Keep child parent&pos for in case of failure
667 Widget
*pOriContainer
= pWidget
->up();
668 unsigned int oriChildPos
= pOriContainer
->getChildPos( pWidget
);
670 // Get parent&sibling before removing it, since relations get cut
671 Widget
*pSibling
= up
? pWidget
->prev() : pWidget
->next();
672 Widget
*pContainer
= pWidget
->up();
676 // try to swap with parent or child
677 // We need to allow for this at least for the root node...
682 if ( pContainer
->swapWithChild( pWidget
) )
687 // TODO: this is a nice feature, but we probably want to do it explicitely...
689 if ( pWidget
->down() && pWidget
->swapWithChild( pWidget
->down() ) )
695 pContainer
->removeChild( pWidget
);
697 // if has up sibling -- append to it, else swap with it
700 if ( pSibling
->addChild( pWidget
, up
? 0xffff : 0 ) )
703 unsigned int childPos
= pContainer
->getChildPos( pSibling
);
704 if ( pContainer
->addChild( pWidget
, childPos
+ (up
? 0 : 1) ) )
705 return true; // should always be succesful
707 // go through parents -- try to get prepended to them
710 for ( ; pContainer
&& pContainer
->up(); pContainer
= pContainer
->up() )
712 unsigned int childPos
= pContainer
->up()->getChildPos( pContainer
);
713 if ( pContainer
->up()->addChild( pWidget
, childPos
+ (up
? 0 : 1) ) )
718 // failed -- try to get it to its old position
719 if ( !pOriContainer
->addChild( pWidget
, oriChildPos
) )
721 // a parent should never reject a child back. but if it ever
722 // happens, just kill it, we don't run an orphanate here ;P
729 // NOTE: root is considered to be number -1
730 Widget
*get( Widget
*pRoot
, int nb
)
733 for ( it
= pRoot
; it
!= NULL
&& nb
>= 0; it
= next( it
) )
738 int get( Widget
*pRoot
, Widget
*pWidget
)
742 for ( it
= pRoot
; it
!= NULL
&& it
!= pWidget
; it
= next( it
) )
748 //** PropertiesList widget
750 class PropertiesList
: public layout::Table
754 friend class PropertiesList
;
756 /* wrapper between the widget and Any */
759 DECL_LINK( ApplyPropertyHdl
, layout::Window
* );
760 DECL_LINK( FlagToggledHdl
, layout::CheckBox
* );
762 AnyWidget( Widget
*pWidget
, rtl::OUString aPropName
, Widget::PropertyKind aPropKind
)
763 : mpWidget( pWidget
), maPropName( aPropName
), maPropKind( aPropKind
)
766 mbBlockFlagCallback
= false;
773 fprintf(stderr
, "~AnyWidget\n");
777 void save( uno::Any aValue
)
779 mpWidget
->setProperty( maPropName
, maPropKind
, aValue
);
785 bool flag
= mpWidget
->isPropertyTouched( maPropName
, maPropKind
);
787 if ( mpFlag
&& mpFlag
->IsChecked() != (BOOL
)flag
)
789 CheckFlag( flag
, true );
793 void CheckFlag( bool bValue
, bool bBlockCallback
)
795 if ( bBlockCallback
)
796 mbBlockFlagCallback
= true;
797 mpFlag
->Check( bValue
);
798 mbBlockFlagCallback
= false;
801 bool bFirstGet
; // HACK
802 rtl::OUString
getValue()
804 // return mpWidget->getOriProperty( maPropName );
806 if ( bFirstGet
) // king of ugliness
807 value
= mpWidget
->getProperty( maPropName
, maPropKind
);
809 value
= mpWidget
->getOriginalProperty( maPropName
, maPropKind
);
814 // FIXME: wrapper should have a base class for this...
815 virtual layout::Window
*getWindow() = 0;
816 virtual layout::Container
*getContainer() { return NULL
; }
818 virtual void load() = 0;
819 virtual void store() = 0;
822 rtl::OUString maPropName
;
823 Widget::PropertyKind maPropKind
;
824 layout::CheckBox
*mpFlag
;
825 bool mbBlockFlagCallback
;
828 struct AnyEdit
: public AnyWidget
, layout::HBox
830 layout::Edit
*mpEdit
;
832 layout::PushButton
*mpExpand
;
833 DECL_LINK( ExpandEditHdl
, layout::PushButton
* );
835 // so we can create widgets (like transforming the Edit into a
837 layout::Window
*mpWinParent
;
839 AnyEdit( Widget
*pWidget
, rtl::OUString aPropName
,
840 Widget::PropertyKind aPropKind
, layout::Window
*pWinParent
)
841 : AnyWidget( pWidget
, aPropName
, aPropKind
), layout::HBox( 0, false ), mpWinParent( pWinParent
)
844 mpExpand
= new layout::PushButton( pWinParent
, WB_TOGGLE
);
845 mpExpand
->SetToggleHdl( LINK( this, AnyEdit
, ExpandEditHdl
) );
846 setAsMultiLine( false );
857 virtual layout::Window
*getWindow()
859 virtual layout::Container
*getContainer()
862 void setAsMultiLine( bool bMultiLine
)
868 text
= mpEdit
->GetText();
869 printf("Remove mpEdit and expand\n");
877 mpEdit
= new layout::Edit( mpWinParent
, WB_BORDER
);
878 mpExpand
->SetText( String::CreateFromAscii( "-" ) );
882 mpEdit
= new layout::Edit( mpWinParent
, WB_BORDER
);
883 mpExpand
->SetText( String::CreateFromAscii( "+" ) );
886 mpEdit
->SetText( text
);
887 mpEdit
->SetModifyHdl( LINK( this, AnyEdit
, ApplyPropertyHdl
) );
889 Add( mpEdit
, true, true, 0 );
890 Add( mpExpand
, false, true, 0 );
892 mbMultiLine
= bMultiLine
;
896 // TODO: make this global... We'll likely need it for export...
898 const char *ori
, *dest
;
900 static rtl::OUString
stringReplace( rtl::OUString _str
,
903 const sal_Unicode
*str
= _str
.getStr();
904 rtl::OUStringBuffer buf
;
906 for ( i
= 0; i
< _str
.getLength(); i
++ )
908 for ( j
= 0; trans
[ j
].ori
; j
++ )
910 const char *ori
= trans
[ j
].ori
;
911 for ( k
= 0; ori
[ k
] && i
+k
< _str
.getLength(); k
++ )
912 if ( ori
[ k
] != str
[ i
+k
] )
917 buf
.appendAscii( trans
[ j
].dest
);
922 buf
.append( str
[ i
] );
924 return buf
.makeStringAndClear();
931 // replace end of lines by "\\n" strings
932 Translate trans
[] = {
933 { "\\", "\\\\" }, { "\n", "\\n" }, { 0, 0 }
935 rtl::OUString str
= anyToString( getValue() );
936 str
= stringReplace( str
, trans
);
939 mpEdit
->SetText( getValue() );
946 // replace "\\n" strings by actual end of lines
947 Translate trans
[] = {
948 { "\\\\", "\\" }, { "\\n", "\n" },
949 { "\\", "" }, { 0, 0 }
951 rtl::OUString str
= GetText();
952 str
= stringReplace( str
, trans
);
953 save( uno::makeAny( str
) );
955 save( uno::makeAny( (rtl::OUString
) mpEdit
->GetText() ) );
959 struct AnyInteger
: public AnyWidget
, NumericField
961 AnyInteger( Widget
*pWidget
, rtl::OUString aPropName
,
962 Widget::PropertyKind aPropKind
, Window
*pWinParent
)
963 : AnyWidget( pWidget
, aPropName
, aPropKind
), NumericField( pWinParent
, WB_SPIN
|WB_BORDER
)
966 SetModifyHdl( LINK( this, AnyInteger
, ApplyPropertyHdl
) );
969 virtual Window
*getWindow()
974 OUString text
= getValue();
975 SetText( text
.getStr() );
982 fprintf(stderr
, "store number: %ld\n", rtl::OUString( GetText() ).toInt64());
984 save( uno::makeAny( rtl::OUString( GetText() ).toInt64() ) );
988 struct AnyFloat
: public AnyInteger
990 AnyFloat( Widget
*pWidget
, rtl::OUString aPropName
,
991 Widget::PropertyKind aPropKind
, Window
*pWinParent
)
992 : AnyInteger( pWidget
, aPropName
, aPropKind
, pWinParent
)
997 save( uno::makeAny( rtl::OUString( GetText() ).toDouble() ) );
1001 struct AnyCheckBox
: public AnyWidget
, layout::CheckBox
1003 AnyCheckBox( Widget
*pWidget
, rtl::OUString aPropName
,
1004 Widget::PropertyKind aPropKind
, layout::Window
*pWinParent
)
1005 : AnyWidget( pWidget
, aPropName
, aPropKind
), layout::CheckBox( pWinParent
)
1007 // adding some whitespaces to make the hit area larger
1008 // SetText( String::CreateFromAscii( "" ) );
1010 SetToggleHdl( LINK( this, AnyWidget
, ApplyPropertyHdl
) );
1013 virtual ~AnyCheckBox()
1016 fprintf(stderr
, "~AnyCheckBox\n");
1020 virtual layout::Window
*getWindow()
1026 fprintf(stderr
, "loading boolean value\n");
1028 Check( getValue().toInt64() != 0 );
1033 virtual void store()
1035 save( uno::makeAny( IsChecked() ) );
1041 SetText( String::CreateFromAscii( IsChecked() ? "true" : "false" ) );
1045 struct AnyListBox
: public AnyWidget
, layout::ListBox
1047 AnyListBox( Widget
*pWidget
, rtl::OUString aPropName
,
1048 Widget::PropertyKind aPropKind
, Window
*pWinParent
)
1049 : AnyWidget( pWidget
, aPropName
, aPropKind
), layout::ListBox( pWinParent
, WB_DROPDOWN
)
1051 SetSelectHdl( LINK( this, AnyWidget
, ApplyPropertyHdl
) );
1054 virtual layout::Window
*getWindow()
1059 SelectEntryPos( sal::static_int_cast
< USHORT
>( getValue().toInt32() ) );
1063 virtual void store()
1065 save( uno::makeAny( (short) GetSelectEntryPos() ) );
1069 struct AnyAlign
: public AnyListBox
1071 AnyAlign( Widget
*pWidget
, rtl::OUString aPropName
,
1072 Widget::PropertyKind aPropKind
, Window
*pWinParent
)
1073 : AnyListBox( pWidget
, aPropName
, aPropKind
, pWinParent
)
1075 InsertEntry( XubString::CreateFromAscii( "Left" ) );
1076 InsertEntry( XubString::CreateFromAscii( "Center" ) );
1077 InsertEntry( XubString::CreateFromAscii( "Right" ) );
1082 /* AnyListBox and AnyComboBox different in that a ComboBox allows the user
1083 to add other options, operating in strings, instead of constants.
1084 (its more like a suggestive AnyEdit) */
1085 struct AnyComboBox
: public AnyWidget
, layout::ComboBox
1087 AnyComboBox( Widget
*pWidget
, rtl::OUString aPropName
,
1088 Widget::PropertyKind aPropKind
, Window
*pWinParent
)
1089 : AnyWidget( pWidget
, aPropName
, aPropKind
), layout::ComboBox( pWinParent
, WB_DROPDOWN
)
1091 SetModifyHdl( LINK( this, AnyComboBox
, ApplyPropertyHdl
) );
1094 virtual layout::Window
*getWindow()
1099 SetText( getValue() );
1103 virtual void store()
1105 save( uno::makeAny( (rtl::OUString
) GetText() ) );
1109 struct AnyFontStyle
: public AnyComboBox
1111 AnyFontStyle( Widget
*pWidget
, rtl::OUString aPropName
,
1112 Widget::PropertyKind aPropKind
, Window
*pWinParent
)
1113 : AnyComboBox( pWidget
, aPropName
, aPropKind
, pWinParent
)
1115 InsertEntry( XubString::CreateFromAscii( "Bold" ) );
1116 InsertEntry( XubString::CreateFromAscii( "Italic" ) );
1117 InsertEntry( XubString::CreateFromAscii( "Bold Italic" ) );
1118 InsertEntry( XubString::CreateFromAscii( "Fett" ) );
1123 layout::FixedText
*mpLabel
;
1124 layout::CheckBox
*mpFlag
;
1128 PropertyEntry( layout::Window
*pWinParent
, AnyWidget
*pAnyWidget
)
1130 mpLabel
= new layout::FixedText( pWinParent
);
1132 // append ':' to aPropName
1133 rtl::OUStringBuffer
buf( pAnyWidget
->maPropName
);
1134 buf
.append( sal_Unicode (':') );
1135 mpLabel
->SetText( buf
.makeStringAndClear() );
1137 mpValue
= pAnyWidget
;
1138 mpFlag
= new layout::CheckBox( pWinParent
);
1139 mpFlag
->SetToggleHdl( LINK( mpValue
, AnyWidget
, FlagToggledHdl
) );
1140 mpValue
->mpFlag
= mpFlag
;
1146 fprintf(stderr
, "REMOVING label, flag and value\n");
1153 // Use this factory rather than the constructor -- check for NULL
1154 static PropertyEntry
*construct( Widget
*pWidget
, rtl::OUString aPropName
,
1155 Widget::PropertyKind aPropKind
, sal_uInt16 nType
,
1156 layout::Window
*pWinParent
)
1158 AnyWidget
*pAnyWidget
;
1160 case uno::TypeClass_STRING
:
1161 if ( aPropName
.compareToAscii( "FontStyleName" ) == 0 )
1163 pAnyWidget
= new AnyFontStyle( pWidget
, aPropName
, aPropKind
, pWinParent
);
1166 pAnyWidget
= new AnyEdit( pWidget
, aPropName
, aPropKind
, pWinParent
);
1168 case uno::TypeClass_SHORT
:
1169 if ( aPropName
.compareToAscii( "Align" ) == 0 )
1171 pAnyWidget
= new AnyAlign( pWidget
, aPropName
, aPropKind
, pWinParent
);
1174 // otherwise, treat as any other number...
1175 case uno::TypeClass_LONG
:
1176 case uno::TypeClass_UNSIGNED_LONG
:
1177 pAnyWidget
= new AnyInteger( pWidget
, aPropName
, aPropKind
, pWinParent
);
1179 case uno::TypeClass_FLOAT
:
1180 case uno::TypeClass_DOUBLE
:
1181 pAnyWidget
= new AnyFloat( pWidget
, aPropName
, aPropKind
, pWinParent
);
1183 case uno::TypeClass_BOOLEAN
:
1184 pAnyWidget
= new AnyCheckBox( pWidget
, aPropName
, aPropKind
, pWinParent
);
1189 return new PropertyEntry( pWinParent
, pAnyWidget
);
1193 layout::Window
*mpParentWindow
;
1195 std::list
< PropertyEntry
* > maPropertiesList
;
1196 layout::FixedLine
*mpSeparator
;
1198 // some properties are obscure, or simply don't make sense in this
1199 // context. Let's just ignore them.
1200 // Maybe we could offer them in an expander or something...
1201 static bool toIgnore( rtl::OUString prop
)
1203 // binary search -- keep the list sorted alphabetically
1204 static char const *toIgnoreList
[] = {
1205 "DefaultControl", "FocusOnClick", "FontCharWidth", "FontCharset",
1206 "FontEmphasisMark", "FontFamily", "FontHeight", "FontKerning", "FontName",
1207 "FontOrientation", "FontPitch", "FontRelief", "FontSlant", "FontStrikeout",
1208 "FontType", "FontWordLineMode", "HelpText", "HelpURL", "MultiLine",
1209 "Printable", "Repeat", "RepeatDelay", "Tabstop"
1213 // checks list sanity -- enable this when you add some entries...
1214 for ( unsigned int i
= 1; i
< sizeof( toIgnoreList
)/sizeof( char * ); i
++ )
1216 if ( strcmp(toIgnoreList
[i
-1], toIgnoreList
[i
]) >= 0 )
1218 printf("ignore list not ordered properly: "
1219 "'%s' should come before '%s'\n",
1220 toIgnoreList
[i
], toIgnoreList
[i
-1]);
1226 int min
= 0, max
= sizeof( toIgnoreList
)/sizeof( char * ) - 1, mid
, cmp
;
1228 mid
= min
+ (max
- min
)/2;
1229 cmp
= prop
.compareToAscii( toIgnoreList
[ mid
] );
1236 } while ( min
<= max
);
1241 PropertiesList( layout::Dialog
*dialog
)
1242 : layout::Table( dialog
, "properties-box" )
1243 , mpParentWindow( dialog
), mpSeparator( 0 )
1253 // auxiliary, add properties from the peer to the list
1254 void addProperties( Widget
*pWidget
, Widget::PropertyKind rKind
)
1256 Widget::PropertyIterator
it( pWidget
, rKind
);
1257 while ( it
.hasNext() )
1259 beans::Property prop
= it
.next();
1260 rtl::OUString
name( prop
.Name
);
1261 if ( toIgnore( name
) )
1263 sal_uInt16 type
= static_cast< sal_uInt16
>( prop
.Type
.getTypeClass() );
1265 PropertyEntry
*propEntry
= PropertyEntry::construct(
1266 pWidget
, name
, rKind
, type
, mpParentWindow
);
1270 Add( propEntry
->mpLabel
, false, false );
1272 // HACK: one of these will return Null...
1273 Add( propEntry
->mpValue
->getWindow(), true, false );
1274 Add( propEntry
->mpValue
->getContainer(), true, false );
1276 Add( propEntry
->mpFlag
, false, false );
1277 maPropertiesList
.push_back( propEntry
);
1283 void selectedWidget( Widget
*pWidget
)
1290 addProperties( pWidget
, Widget::CONTAINER_PROPERTY
);
1292 mpSeparator
= new layout::FixedLine( mpParentWindow
);
1293 // TODO: we may want to have to separate list widgets here...
1294 Add( mpSeparator
, false, false, 3, 1 );
1296 addProperties( pWidget
, Widget::WINDOW_PROPERTY
);
1306 for ( std::list
< PropertyEntry
* >::iterator it
= maPropertiesList
.begin();
1307 it
!= maPropertiesList
.end(); it
++)
1309 maPropertiesList
.clear();
1316 IMPL_LINK( PropertiesList::PropertyEntry::AnyWidget
, ApplyPropertyHdl
, layout::Window
*, pWin
)
1323 IMPL_LINK( PropertiesList::PropertyEntry::AnyWidget
, FlagToggledHdl
, layout::CheckBox
*, pCheck
)
1326 fprintf(stderr
, "Property flag pressed -- is: %d\n", pCheck
->IsChecked());
1328 if ( !mbBlockFlagCallback
)
1330 bool checked
= pCheck
->IsChecked();
1331 if ( !checked
) // revert
1334 fprintf(stderr
, "revert\n");
1341 fprintf(stderr
, "user can't dirty the flag!\n");
1343 // User can't flag the property as dirty
1344 // Actually, we may want to allow the designer to force a property to be stored.
1345 // Could be useful when the default value of some new property wasn't yet decided...
1346 CheckFlag( false, true );
1351 fprintf(stderr
, "Property flag pressed -- BLOCKED\n");
1356 IMPL_LINK( PropertiesList::PropertyEntry::AnyEdit
, ExpandEditHdl
, layout::PushButton
*, pBtn
)
1358 setAsMultiLine( pBtn
->IsChecked() );
1362 //** SortListBox auxiliary widget
1365 { // For a manual sort ListBox; asks for a ListBox and Up/Down/Remove
1367 DECL_LINK( ItemSelectedHdl
, layout::ListBox
* );
1368 DECL_LINK( UpPressedHdl
, layout::Button
* );
1369 DECL_LINK( DownPressedHdl
, layout::Button
* );
1370 DECL_LINK( RemovePressedHdl
, layout::Button
* );
1371 layout::PushButton
*mpUpButton
, *mpDownButton
, *mpRemoveButton
;
1374 layout::ListBox
*mpListBox
;
1376 virtual void upPressed( USHORT nPos
)
1378 XubString str
= mpListBox
->GetSelectEntry();
1379 mpListBox
->RemoveEntry( nPos
);
1380 nPos
= mpListBox
->InsertEntry( str
, nPos
-1 );
1381 mpListBox
->SelectEntryPos( nPos
);
1384 virtual void downPressed( USHORT nPos
)
1386 XubString str
= mpListBox
->GetSelectEntry();
1387 mpListBox
->RemoveEntry( nPos
);
1388 nPos
= mpListBox
->InsertEntry( str
, nPos
+1 );
1389 mpListBox
->SelectEntryPos( nPos
);
1392 virtual void removePressed( USHORT nPos
)
1394 mpListBox
->RemoveEntry( nPos
);
1397 virtual void itemSelected( USHORT nPos
)
1399 // if we had some XLayoutContainer::canAdd() or maxChildren() function
1400 // we could make a function to check if we can move selected and enable/
1401 // /disable the move buttons as appropriate
1403 if ( nPos
== LISTBOX_ENTRY_NOTFOUND
)
1405 mpUpButton
->Disable();
1406 mpDownButton
->Disable();
1407 mpRemoveButton
->Disable();
1411 mpUpButton
->Enable();
1412 mpDownButton
->Enable();
1413 mpRemoveButton
->Enable();
1418 SortListBox( layout::ListBox
*pListBox
, layout::PushButton
*pUpButton
, layout::PushButton
*pDownButton
,
1419 layout::PushButton
*pRemoveButton
)
1420 : mpUpButton( pUpButton
), mpDownButton( pDownButton
), mpRemoveButton( pRemoveButton
),
1421 mpListBox( pListBox
)
1423 mpListBox
->SetSelectHdl( LINK( this, SortListBox
, ItemSelectedHdl
) );
1425 mpUpButton
->SetModeImage( layout::Image ( "res/commandimagelist/lc_moveup.png" ) );
1426 mpUpButton
->SetImageAlign( IMAGEALIGN_LEFT
);
1427 mpUpButton
->SetClickHdl( LINK( this, SortListBox
, UpPressedHdl
) );
1429 mpDownButton
->SetModeImage( layout::Image ( "res/commandimagelist/lc_movedown.png" ) );
1430 mpDownButton
->SetImageAlign( IMAGEALIGN_LEFT
);
1431 mpDownButton
->SetClickHdl( LINK( this, SortListBox
, DownPressedHdl
) );
1433 // "res/commandimagelist/lch_delete.png", "res/commandimagelist/lc_delete.png"
1434 mpRemoveButton
->SetModeImage( layout::Image ( "res/commandimagelist/sc_closedoc.png" ) );
1435 mpRemoveButton
->SetImageAlign( IMAGEALIGN_LEFT
);
1436 mpRemoveButton
->SetClickHdl( LINK( this, SortListBox
, RemovePressedHdl
) );
1438 // fire an un-select event
1439 itemSelected( LISTBOX_ENTRY_NOTFOUND
);
1442 virtual ~SortListBox();
1445 SortListBox::~SortListBox()
1449 delete mpDownButton
;
1450 delete mpRemoveButton
;
1453 IMPL_LINK( SortListBox
, UpPressedHdl
, layout::Button
*, pBtn
)
1456 USHORT pos
= mpListBox
->GetSelectEntryPos();
1457 if ( pos
> 0 && pos
!= LISTBOX_ENTRY_NOTFOUND
)
1462 IMPL_LINK( SortListBox
, DownPressedHdl
, layout::Button
*, pBtn
)
1465 USHORT pos
= mpListBox
->GetSelectEntryPos();
1466 if ( pos
< mpListBox
->GetEntryCount() && pos
!= LISTBOX_ENTRY_NOTFOUND
)
1471 IMPL_LINK( SortListBox
, RemovePressedHdl
, layout::Button
*, pBtn
)
1474 USHORT pos
= mpListBox
->GetSelectEntryPos();
1475 if ( pos
!= LISTBOX_ENTRY_NOTFOUND
)
1476 removePressed( pos
);
1480 IMPL_LINK( SortListBox
, ItemSelectedHdl
, layout::ListBox
*, pList
)
1483 USHORT pos
= mpListBox
->GetSelectEntryPos();
1484 itemSelected( pos
);
1488 //** LayoutTree widget
1490 class LayoutTree
: public SortListBox
1495 virtual void widgetSelected( Widget
*pWidget
) = 0;
1499 Listener
*mpListener
;
1502 Widget
*mpRootWidget
;
1504 LayoutTree( layout::Dialog
*dialog
)
1505 : SortListBox( new layout::ListBox( dialog
, "layout-tree" ),
1506 new layout::PushButton( dialog
, "layout-up-button" ),
1507 new layout::PushButton( dialog
, "layout-down-button" ),
1508 new layout::PushButton( dialog
, "layout-remove-button" ) )
1510 layout::PeerHandle handle
= dialog
->GetPeerHandle( "preview-box" );
1511 uno::Reference
< awt::XLayoutConstrains
> xWidget( handle
, uno::UNO_QUERY
);
1512 mpRootWidget
= new Widget( xWidget
, "root" );
1515 virtual ~LayoutTree();
1517 Widget
*getWidget( int nPos
)
1519 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
1520 return FlatLayout::get( mpRootWidget
, nPos
);
1524 Widget
*getSelectedWidget()
1526 Widget
*pWidget
= getWidget( mpListBox
->GetSelectEntryPos() );
1527 if ( !pWidget
) // return root, if none selected
1528 pWidget
= mpRootWidget
;
1532 void selectWidget( Widget
*pWidget
)
1534 int pos
= FlatLayout::get( mpRootWidget
, pWidget
);
1536 // if asked to select hidden root, select visible root
1538 mpListBox
->SelectEntryPos( sal::static_int_cast
< USHORT
>( pos
) );
1545 // pads a string with whitespaces
1546 static rtl::OUString
padString( rtl::OUString name
, int depth
)
1548 rtl::OStringBuffer
aBuf( depth
* 4 + name
.getLength() + 2 );
1549 for (int i
= 0; i
< depth
; i
++)
1551 aBuf
.append( rtl::OUStringToOString( name
, RTL_TEXTENCODING_ASCII_US
) );
1552 return rtl::OUString( aBuf
.getStr(), aBuf
.getLength(),
1553 RTL_TEXTENCODING_UTF8
);
1558 for ( Widget
*i
= FlatLayout::next( mpRootWidget
); i
; i
= FlatLayout::next( i
) )
1559 mpListBox
->InsertEntry( inner::padString( i
->getLabel(), i
->getDepth()-1 ) );
1561 // any selection, no longer is. ListBox doesn't fire the event on this case;
1563 itemSelected( LISTBOX_ENTRY_NOTFOUND
);
1566 void setListener( Listener
*pListener
)
1567 { mpListener
= pListener
; }
1569 // print in XML format...
1571 static rtl::OUString
toXMLNaming (const rtl::OUString
&string
)
1573 rtl::OUStringBuffer
buffer (string
.getLength());
1574 sal_Unicode
*str
= string
.pData
->buffer
;
1575 for (int i
= 0; i
< string
.getLength(); i
++) {
1576 if ( str
[i
] >= 'A' && str
[i
] <= 'Z' )
1579 buffer
.append ((sal_Unicode
) '-');
1580 buffer
.append ((sal_Unicode
) (str
[i
] - 'A' + 'a'));
1583 buffer
.append ((sal_Unicode
) str
[i
]);
1586 return buffer
.makeStringAndClear();
1591 printf("\t\tExport:\n");
1592 printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1593 "<dialog xmlns=\"http://openoffice.org/2007/layout\"\n"
1594 " xmlns:cnt=\"http://openoffice.org/2007/layout/container\"\n"
1595 " id=\"dialog\" title=\"Unnamed\" sizeable=\"true\" >\n");
1597 for ( Widget
*i
= FlatLayout::next( mpRootWidget
); i
; i
= FlatLayout::next( i
) )
1599 for ( int d
= i
->getDepth(); d
> 0; d
-- )
1601 printf("<%s ", OUSTRING_CSTR( i
->getUnoName() ) );
1603 for ( int kind
= 0; kind
< 2; kind
++ )
1605 Widget::PropertyKind wKind
= kind
== 0 ? Widget::WINDOW_PROPERTY
1606 : Widget::CONTAINER_PROPERTY
;
1607 Widget::PropertyIterator
it( i
, wKind
);
1608 while ( it
.hasNext() )
1610 beans::Property prop
= it
.next();
1611 if ( !i
->isPropertyTouched( prop
.Name
, wKind
) )
1614 rtl::OUString value
= i
->getProperty( prop
.Name
, wKind
);
1615 if ( prop
.Type
.getTypeClass() == uno::TypeClass_BOOLEAN
)
1617 if ( value
.compareToAscii( "0" ) )
1618 value
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("false") );
1620 value
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("true") );
1623 if ( value
.getLength() > 0 )
1624 printf("%s%s=\"%s\" ",
1625 kind
== 0 ? "" : "cnt:",
1626 OUSTRING_CSTR( toXMLNaming( prop
.Name
) ), OUSTRING_CSTR( value
)
1633 printf("</dialog>\n");
1637 virtual void upPressed( USHORT nPos
)
1639 Widget
*pWidget
= getWidget( nPos
);
1640 if ( FlatLayout::moveWidget( pWidget
, true ) )
1642 selectWidget( pWidget
);
1645 virtual void downPressed( USHORT nPos
)
1647 Widget
*pWidget
= getWidget( nPos
);
1648 if ( FlatLayout::moveWidget( pWidget
, false ) )
1650 selectWidget( pWidget
);
1653 virtual void removePressed( USHORT nPos
)
1655 Widget
*pWidget
= getWidget( nPos
);
1658 pWidget
->up()->removeChild( pWidget
);
1664 virtual void itemSelected( USHORT nPos
)
1666 mpListener
->widgetSelected( getWidget( nPos
) );
1667 SortListBox::itemSelected( nPos
);
1671 LayoutTree::~LayoutTree()
1673 delete mpRootWidget
;
1678 class EditorImpl
: public LayoutTree::Listener
1680 void createWidget( const char *unoName
);
1682 PropertiesList
*mpPropertiesList
;
1683 LayoutTree
*mpLayoutTree
;
1685 layout::PushButton
*pImportButton
, *pExportButton
;
1687 FileDialog
*pImportDialog
;
1689 DECL_LINK( ImportButtonHdl
, layout::PushButton
* );
1690 DECL_LINK( ExportButtonHdl
, layout::PushButton
* );
1692 DECL_LINK( ImportDialogHdl
, FileDialog
* );
1696 uno::Reference
< lang::XMultiServiceFactory
> mxFactory
;
1697 uno::Reference
< awt::XToolkit
> mxToolkit
;
1698 uno::Reference
< awt::XWindow
> mxToplevel
;
1700 virtual void widgetSelected( Widget
*pWidget
);
1701 DECL_LINK( CreateWidgetHdl
, layout::Button
* );
1703 std::list
< layout::PushButton
*> maCreateButtons
;
1707 EditorImpl( layout::Dialog
*dialog
,
1708 // we should probable open this channel (or whatever its called) ourselves
1709 uno::Reference
< lang::XMultiServiceFactory
> xMSF
);
1710 virtual ~EditorImpl();
1712 void loadFile( const rtl::OUString
&aTestFile
);
1715 EditorImpl::EditorImpl( layout::Dialog
*dialog
,
1716 uno::Reference
< lang::XMultiServiceFactory
> xFactory
)
1717 : mxFactory( xFactory
)
1718 , mxToplevel( dialog
->GetPeerHandle( "dialog" ), uno::UNO_QUERY
)
1719 // FIXME: any of these should work
1720 //dialog->getContext()->getRoot(), uno::UNO_QUERY )
1721 // dialog->GetPeer(), uno::UNO_QUERY )
1724 fprintf (stderr
, "EditorImpl()\n");
1727 mxToolkit
= uno::Reference
< awt::XToolkit
>(
1728 mxFactory
->createInstance(
1729 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.Toolkit" ) ) ),
1731 OSL_ASSERT( mxToolkit
.is() );
1735 fprintf (stderr
, "custom widgets\n");
1737 mpPropertiesList
= new PropertiesList( dialog
);
1739 mpLayoutTree
= new LayoutTree( dialog
);
1740 mpLayoutTree
->setListener( this );
1742 /* if ( xImport.is() )
1743 mpLayoutTree->getWidget( -1 )->addChild( new Widget( xImport, "import" ) );*/
1746 layout::Container
aWidgets( dialog
, "create-widget" );
1747 layout::Container
aContainers( dialog
, "create-container" );
1748 for ( int i
= 0; i
< WIDGETS_SPECS_LEN
; i
++ )
1750 layout::PushButton
*pBtn
= new layout::PushButton( (layout::Window
*) dialog
);
1751 pBtn
->SetText( rtl::OUString::createFromAscii( WIDGETS_SPECS
[ i
].pLabel
) );
1752 pBtn
->SetClickHdl( LINK( this, EditorImpl
, CreateWidgetHdl
) );
1753 if ( WIDGETS_SPECS
[ i
].pIconName
!= NULL
)
1755 rtl::OString
aPath ("res/commandimagelist/");
1756 aPath
+= WIDGETS_SPECS
[ i
].pIconName
;
1757 layout::Image
aImg( aPath
);
1758 pBtn
->SetModeImage( aImg
);
1759 pBtn
->SetImageAlign( IMAGEALIGN_LEFT
);
1762 maCreateButtons
.push_back( pBtn
);
1763 layout::Container
*pBox
= WIDGETS_SPECS
[ i
].bIsContainer
? &aContainers
: &aWidgets
;
1768 fprintf(stderr
,"creating file dialog\n");
1769 pImportDialog
= new FileDialog( NULL
/*(layout::Window *) dialog*/, 0 );
1770 fprintf(stderr
,"connecting it\n");
1771 pImportDialog
->SetFileSelectHdl( LINK( this, EditorImpl
, ImportDialogHdl
) );
1772 fprintf(stderr
,"done file dialog\n");
1775 /* pImportButton = new layout::PushButton( dialog, "import-button" );
1776 pImportButton->SetClickHdl( LINK( this, EditorImpl, ImportButtonHdl ) );*/
1777 pExportButton
= new layout::PushButton( dialog
, "export-button" );
1778 pExportButton
->SetClickHdl( LINK( this, EditorImpl
, ExportButtonHdl
) );
1781 EditorImpl::~EditorImpl()
1783 delete mpPropertiesList
;
1784 delete mpLayoutTree
;
1785 for ( std::list
< layout::PushButton
* >::const_iterator i
= maCreateButtons
.begin();
1786 i
!= maCreateButtons
.end(); i
++)
1788 delete pImportButton
;
1789 delete pExportButton
;
1791 delete pImportDialog
;
1795 void EditorImpl::loadFile( const rtl::OUString
&aTestFile
)
1797 fprintf( stderr
, "TEST: layout instance\n" );
1798 uno::Reference
< awt::XLayoutRoot
> xRoot
1799 ( new EditorRoot( mxFactory
, mpLayoutTree
->mpRootWidget
) );
1802 mxMSF->createInstance
1803 ( ::rtl::OUString::createFromAscii( "com.sun.star.awt.Layout" ) ),
1808 throw uno::RuntimeException(
1809 OUString( RTL_CONSTASCII_USTRINGPARAM("could not create awt Layout component!") ),
1810 uno::Reference
< uno::XInterface
>() );
1814 fprintf( stderr
, "TEST: initing root\n" );
1817 uno::Reference
< lang::XInitialization
> xInit( xRoot
, uno::UNO_QUERY
);
1820 throw uno::RuntimeException(
1821 OUString( RTL_CONSTASCII_USTRINGPARAM("Layout has no XInitialization!") ),
1822 uno::Reference
< uno::XInterface
>() );
1826 fprintf( stderr
, "TEST: running parser\n" );
1828 uno::Sequence
< uno::Any
> aParams( 1 );
1829 aParams
[0] <<= aTestFile
;
1831 fprintf( stderr
, "TEST: do it\n" );
1833 xInit
->initialize( aParams
);
1835 fprintf( stderr
, "TEST: file loaded\n" );
1838 mpLayoutTree
->rebuild();
1841 void EditorImpl::createWidget( const char *name
)
1843 Widget
*pWidget
= mpLayoutTree
->getSelectedWidget();
1845 Widget
*pChild
= new Widget( rtl::OUString(), mxToolkit
, uno::Reference
< awt::XLayoutContainer
>( mxToplevel
, uno::UNO_QUERY
), rtl::OUString::createFromAscii( name
), awt::WindowAttribute::SHOW
);
1846 if ( !pWidget
->addChild( pChild
) )
1849 // we may want to popup an error message
1853 mpLayoutTree
->rebuild();
1854 mpLayoutTree
->selectWidget( pWidget
);
1858 void EditorImpl::widgetSelected( Widget
*pWidget
)
1860 // we know can't add widget to a non-container, so let's disable the create
1861 // buttons then. Would be nice to have a method to check if a container is
1863 if ( !pWidget
|| pWidget
->isContainer() )
1865 for ( std::list
< layout::PushButton
*>::const_iterator it
= maCreateButtons
.begin();
1866 it
!= maCreateButtons
.end(); it
++)
1871 for ( std::list
< layout::PushButton
*>::const_iterator it
= maCreateButtons
.begin();
1872 it
!= maCreateButtons
.end(); it
++)
1876 mpPropertiesList
->selectedWidget( pWidget
);
1879 IMPL_LINK( EditorImpl
, CreateWidgetHdl
, layout::Button
*, pBtn
)
1882 for ( std::list
< layout::PushButton
*>::const_iterator it
= maCreateButtons
.begin();
1883 it
!= maCreateButtons
.end(); it
++, i
++ )
1888 OSL_ASSERT( i
< WIDGETS_SPECS_LEN
);
1889 createWidget( WIDGETS_SPECS
[i
].pName
);
1893 IMPL_LINK( EditorImpl
, ImportButtonHdl
, layout::PushButton
*, pBtn
)
1897 fprintf(stderr
, "IMPORT!\n");
1900 pImportDialog
->Execute();
1907 IMPL_LINK( EditorImpl
, ImportDialogHdl
, FileDialog
*, pDialog
)
1909 UniString path
= pDialog
->GetPath();
1910 //fprintf(stderr, "Executing import dialog!\n");
1913 fprintf(stderr
, "got import file: %s\n",rtl::OUStringToOString( path
, RTL_TEXTENCODING_ASCII_US
).getStr() );
1920 IMPL_LINK( EditorImpl
, ExportButtonHdl
, layout::PushButton
*, pBtn
)
1923 mpLayoutTree
->print();
1927 //** Editor, the Dialog
1929 Editor::Editor( uno::Reference
< lang::XMultiServiceFactory
> xFactory
,
1930 rtl::OUString aFile
)
1931 : layout::Dialog( (Window
*) (NULL
), "editor.xml", "dialog" )
1932 , mpImpl( new EditorImpl( this, xFactory
) )
1934 if ( aFile
.getLength() )
1935 mpImpl
->loadFile( aFile
);