1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "editor.hxx"
25
26 #undef NDEBUG
27
28 /*
29 #include <stdio.h>
30 #include <string.h>
31 */
32
33 #include <cassert>
34 #include <cstdio>
35 #include <cstring>
36 #include <list>
37 #include <vector>
38
39 #include <com/sun/star/awt/WindowAttribute.hpp>
40 #include <com/sun/star/awt/XLayoutConstrains.hpp>
41 #include <com/sun/star/awt/XLayoutContainer.hpp>
42 #include <com/sun/star/awt/XToolkit.hpp>
43 #include <com/sun/star/awt/XVclWindowPeer.hpp>
44 #include <com/sun/star/awt/XWindow.hpp>
45 #include <com/sun/star/awt/XWindowPeer.hpp>
46 #include <rtl/strbuf.hxx>
47 #include <rtl/ustrbuf.hxx>
48 #include <toolkit/helper/property.hxx>
49 #include <vcl/lstbox.h>
50
51 using namespace layout::css;
52
53 using rtl::OUString;
54
55 // FIXME:
56 //#define FILEDLG
57
58 #include <layout/core/helper.hxx>
59 #include <layout/core/root.hxx>
60 #include <layout/core/helper.hxx>
61
62 // TODO: automatically generated
63 struct WidgetSpec {
64 const char *pLabel, *pName, *pIconName;
65 bool bIsContainer; };
66 static const WidgetSpec WIDGETS_SPECS[] = {
67 { "Label", "fixedtext" , "sc_label.png", false },
68 { "Button", "pushbutton" , "sc_pushbutton.png", false },
69 { "Radio Button", "radiobutton" , "sc_radiobutton.png", false },
70 { "Check Box", "checkbox" , "sc_checkbox.png", false },
71 { "Line Edit", "edit" , "sc_edit.png", false },
72 { "Numeric Field", "numericfield", "sc_numericfield.png", false },
73 { "List Box ", "listbox" , NULL, false },
74 // containers
75 { "Hor Box", "hbox" , NULL, true },
76 { "Ver Box", "vbox" , NULL, true },
77 { "Table", "table" , NULL, true },
78 { "Alignment", "align" , NULL, true },
79 { "Tab Control", "tabcontrol" , NULL, true },
80 { "Hor Splitter", "hsplitter" , NULL, true },
81 { "Ver Splitter", "vsplitter" , NULL, true },
82 { "Scroller", "scroller" , NULL, true },
83 };
84 const int WIDGETS_SPECS_LEN = sizeof (WIDGETS_SPECS) / sizeof (WidgetSpec);
85
86 using namespace layout;
87 using namespace layoutimpl;
88 namespace css = ::com::sun::star;
89
anyToString(uno::Any value)90 static rtl::OUString anyToString (uno::Any value)
91 {
92 try
93 {
94 switch (value.getValueTypeClass()) {
95 case uno::TypeClass_STRING:
96 return value.get<rtl::OUString>();
97 case uno::TypeClass_CONSTANT:
98 return rtl::OUString::valueOf (value.get<sal_Int32>());
99 case uno::TypeClass_LONG:
100 return rtl::OUString::valueOf (value.get<sal_Int64>());
101 case uno::TypeClass_SHORT:
102 // FIXME: seems broken
103 return rtl::OUString::valueOf ((sal_Int32) value.get<short>());
104
105 case uno::TypeClass_FLOAT:
106 return rtl::OUString::valueOf (value.get<float>());
107 case uno::TypeClass_DOUBLE:
108 return rtl::OUString::valueOf (value.get<double>());
109
110 case uno::TypeClass_BOOLEAN:
111 {
112 bool val = value.get<sal_Bool>();
113 return rtl::OUString( val ? "1" : "0", 1, RTL_TEXTENCODING_ASCII_US );
114 /* if ( val )
115 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
116 else
117 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) );*/
118 }
119 default:
120 break;
121 }
122 }
123 catch(...) {}
124 return rtl::OUString();
125 }
126
anyToNatural(uno::Any value)127 static inline long anyToNatural (uno::Any value)
128 { return sal::static_int_cast<long>(anyToString( value ).toInt64()); }
anyToDecimal(uno::Any value)129 static inline double anyToDecimal (uno::Any value)
130 { return anyToString( value ).toDouble(); }
131
132 /* XLayoutContainer/XLayoutConstrains are a bit of a hasle to work with.
133 Let's wrap them. */
134 class Widget : public layoutimpl::LayoutWidget
135 {
136 friend class EditorRoot;
137
138 Widget *mpParent;
139 std::vector< Widget *> maChildren;
140 bool mbForeign;
141
142 rtl::OUString mrId;
143 rtl::OUString mrLabel, mrUnoName;
144
145 // TODO: store original properties. And some property handling methods.
146 long mnOriAttrbs;
147 layoutimpl::PropList maOriProps, maOriChildProps;
148
149 public:
150
151 // to be used to wrap the root
Widget(uno::Reference<awt::XLayoutConstrains> xImport,const char * label)152 Widget( uno::Reference< awt::XLayoutConstrains > xImport, const char *label )
153 : mpParent( 0 ), mbForeign( true )
154 {
155 mxWidget = xImport;
156 mxContainer = uno::Reference< awt::XLayoutContainer >( mxWidget, uno::UNO_QUERY );
157
158 mrLabel = rtl::OUString( label, strlen( label ), RTL_TEXTENCODING_UTF8 );
159
160 #if 0 /* obsolete */
161 // FIXME: this code is meant to import a XML file. Just use the importer,
162 // then pass the root widget. But information like the ID string is lost.
163 // So, this needs to be more closely tight to the importer.
164 uno::Sequence< uno::Reference< awt::XLayoutConstrains > > aChildren;
165 for ( int i = 0; i < aChildren.getLength(); i++ )
166 {
167 Widget *pChild = new Widget( aChildren[ i ], "---" );
168 maChildren.push_back( pChild );
169 pChild->mpParent = this;
170 }
171 #endif
172 }
173
Widget(rtl::OUString id,uno::Reference<awt::XToolkit> xToolkit,uno::Reference<awt::XLayoutContainer> xParent,rtl::OUString unoName,long nAttrbs)174 Widget( rtl::OUString id, uno::Reference< awt::XToolkit > xToolkit,
175 uno::Reference< awt::XLayoutContainer > xParent,
176 rtl::OUString unoName, long nAttrbs )
177 : mpParent( 0 ), mbForeign( false ), mrId( id ),
178 mnOriAttrbs( nAttrbs )
179 {
180 while ( xParent.is() && !uno::Reference< awt::XWindow >( xParent, uno::UNO_QUERY ).is() )
181 {
182 uno::Reference< awt::XLayoutContainer > xContainer( xParent, uno::UNO_QUERY );
183 OSL_ASSERT( xContainer.is() );
184 xParent = uno::Reference< awt::XLayoutContainer >( xContainer->getParent(), uno::UNO_QUERY );
185 }
186
187 mxWidget = WidgetFactory::createWidget( xToolkit, xParent, unoName, nAttrbs );
188 OSL_ASSERT( mxWidget.is() );
189 mxContainer = uno::Reference< awt::XLayoutContainer >( mxWidget, uno::UNO_QUERY );
190
191 mrLabel = mrUnoName = unoName;
192 // try to get a nicer label for the widget
193 for ( int i = 0; i < WIDGETS_SPECS_LEN; i++ )
194 if ( unoName.equalsAscii( WIDGETS_SPECS[ i ].pName ) )
195 {
196 const char *label = WIDGETS_SPECS[ i ].pLabel;
197 mrLabel = rtl::OUString( label, strlen( label ), RTL_TEXTENCODING_UTF8 );
198 break;
199 }
200
201 // set default Text property
202 // TODO: disable editing of text fields, check boxes selected, etc...
203 #if 0
204 uno::Reference< awt::XVclWindowPeer> xVclPeer( mxWidget, uno::UNO_QUERY )
205 if ( xVclPeer.is() ) // XVclWindowPeer ignores missing / incorrect properties
206
207 //FIXME: it looks odd on widgets like NumericField seeing text which is deleted
208 // when you interact with it... We can avoid it for those widgets, by doing a getProp
209 // of "Text" and check if it is empty or not.
210
211 xVclPeer->setProperty( rtl::OUString::createFromAscii( "Text" ),
212 uno::makeAny( rtl::OUString::createFromAscii( "new widget" ) ) );
213 #endif
214
215 // store original properties
216 {
217 PropertyIterator it( this, WINDOW_PROPERTY );
218 while ( it.hasNext() )
219 {
220 beans::Property prop = it.next();
221 rtl::OUString name( prop.Name );
222 rtl::OUString value( getProperty( name, WINDOW_PROPERTY ) );
223 #if DEBUG_PRINT
224 fprintf(stderr, "original property: %s = %s\n", OUSTRING_CSTR(name), OUSTRING_CSTR(value));
225 #endif
226 std::pair< rtl::OUString, rtl::OUString > pair( name, value );
227 maOriProps.push_back( pair );
228 }
229 }
230
231 }
232
~Widget()233 ~Widget()
234 {
235 for ( std::vector< Widget *>::const_iterator it = maChildren.begin();
236 it != maChildren.end(); it++ )
237 delete *it;
238 if ( !mbForeign )
239 {
240 uno::Reference< lang::XComponent > xComp( mxWidget, uno::UNO_QUERY );
241 if ( xComp.is() )
242 // some widgets, like our containers, don't implement this interface...
243 xComp->dispose();
244 }
245 }
246
impl()247 uno::Reference< awt::XLayoutConstrains > impl()
248 {
249 return mxWidget;
250 }
251
252 // LayoutWidget
addChild(LayoutWidget * pChild)253 virtual bool addChild( LayoutWidget *pChild )
254 {
255 return addChild( static_cast< Widget * >( pChild ) );
256 }
257
setProperties(const PropList & rProps)258 virtual void setProperties( const PropList &rProps )
259 {
260 // maOriProps = rProps;
261 LayoutWidget::setProperties( rProps );
262 }
263
setChildProperties(LayoutWidget * pChild,const PropList & rProps)264 virtual void setChildProperties( LayoutWidget *pChild, const PropList &rProps )
265 {
266 maOriChildProps = rProps;
267 LayoutWidget::setChildProperties( pChild, rProps );
268 }
269
270 // tree travel
up()271 Widget *up()
272 {
273 return mpParent;
274 }
275
down()276 Widget *down()
277 {
278 if ( maChildren.empty() )
279 return NULL;
280 return maChildren.front();
281 }
282
next()283 Widget *next()
284 {
285 if ( mpParent )
286 {
287 int pos = mpParent->getChildPos( this );
288 return mpParent->getChild( pos+1 );
289 }
290 return NULL;
291 }
292
prev()293 Widget *prev()
294 {
295 if ( mpParent )
296 {
297 int pos = mpParent->getChildPos( this );
298 return mpParent->getChild( pos-1 );
299 }
300 return NULL;
301 }
302
303 // handle
addChild(Widget * pChild,int pos=0xffff)304 bool addChild( Widget *pChild, int pos = 0xffff )
305 {
306 if ( !mxContainer.is() )
307 return false;
308
309 uno::Sequence< uno::Reference < awt::XLayoutConstrains > > aChildren;
310 aChildren = mxContainer->getChildren();
311 int nChildrenLen = aChildren.getLength();
312
313 // ugly, but let's check if the container is next to full...
314 try {
315 mxContainer->addChild( pChild->mxWidget );
316 }
317 catch( awt::MaxChildrenException ex ) {
318 return false;
319 }
320
321 if ( pos < nChildrenLen )
322 { // if its on the middle, we need to make space for it
323 mxContainer->removeChild( pChild->mxWidget );
324 for ( int i = pos; i < nChildrenLen; i++ )
325 mxContainer->removeChild( aChildren[ i ] );
326 mxContainer->addChild( pChild->mxWidget );
327 for ( int i = pos; i < nChildrenLen; i++ )
328 mxContainer->addChild( aChildren[ i ] );
329 maChildren.insert( maChildren.begin()+pos, pChild );
330 }
331 else
332 maChildren.push_back( pChild );
333
334 OSL_ASSERT( pChild->mpParent == NULL );
335 pChild->mpParent = this;
336
337 // store container props
338 {
339 pChild->maOriChildProps.clear();
340 PropertyIterator it( pChild, CONTAINER_PROPERTY );
341 while ( it.hasNext() )
342 {
343 beans::Property prop = it.next();
344 rtl::OUString name( prop.Name );
345 try {
346 rtl::OUString value( pChild->getProperty( name, CONTAINER_PROPERTY ) );
347 std::pair< rtl::OUString, rtl::OUString > pair( name, value );
348 pChild->maOriChildProps.push_back( pair );
349 } catch ( beans::UnknownPropertyException &rEx ) {
350 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",
351 rtl::OUStringToOString (rEx.Message, RTL_TEXTENCODING_UTF8).getStr());
352 }
353 }
354 }
355
356 return true;
357 }
358
removeChild(Widget * pChild)359 bool removeChild( Widget *pChild )
360 {
361 if ( !mxContainer.is() || pChild->mpParent != this )
362 return false;
363
364 mxContainer->removeChild( pChild->mxWidget );
365
366 unsigned int pos = getChildPos( pChild );
367 if ( pos < maChildren.size() )
368 maChildren.erase( maChildren.begin()+pos );
369 pChild->mpParent = NULL;
370
371 return true;
372 }
373
swapWithChild(Widget * pChild)374 bool swapWithChild( Widget *pChild )
375 {
376 if ( !pChild->isContainer() )
377 return false;
378
379 // remove all child's childrens, and try to add them here
380 removeChild( pChild );
381
382 // keep a copy for failure
383 std::vector< Widget *> aChildren = maChildren;
384 std::vector< Widget *> aChildChildren = pChild->maChildren;
385
386 for ( std::vector< Widget *>::const_iterator it = aChildChildren.begin();
387 it != aChildChildren.end(); it++ )
388 pChild->removeChild( *it );
389
390 for ( std::vector< Widget *>::const_iterator it = aChildChildren.begin();
391 it != aChildChildren.end(); it++ )
392 if ( !addChild( *it ) )
393 { // failure
394 for ( std::vector< Widget *>::const_iterator jt = aChildChildren.begin();
395 jt != it; jt++ )
396 removeChild( *jt );
397 for ( std::vector< Widget *>::const_iterator jt = aChildChildren.begin();
398 jt != aChildChildren.end(); jt++ )
399 pChild->addChild( *jt );
400 return false;
401 }
402
403 Widget *pParent = up();
404
405 if ( pParent )
406 {
407 pParent->removeChild( this );
408 pParent->addChild( pChild );
409 }
410 pChild->addChild( this );
411 return true;
412 }
413
getChildPos(Widget * pChild)414 unsigned int getChildPos( Widget *pChild )
415 {
416 int i = 0;
417 for ( std::vector< Widget *>::const_iterator it = maChildren.begin();
418 it != maChildren.end(); it++, i++ )
419 if ( *it == pChild )
420 break;
421 return i;
422 }
423
getChild(int pos)424 Widget *getChild( int pos )
425 {
426 if ( pos >= 0 && pos < (signed) maChildren.size() )
427 return *(maChildren.begin() + pos);
428 return NULL;
429 }
430
isContainer()431 bool isContainer()
432 { return mxContainer.is(); }
getChildrenLen()433 unsigned int getChildrenLen()
434 { return maChildren.size(); }
435
getLabel() const436 rtl::OUString getLabel() const
437 { return mrLabel; }
getUnoName() const438 rtl::OUString getUnoName() const
439 { return mrUnoName; }
440
getDepth()441 int getDepth()
442 {
443 int depth = 0;
444 for ( Widget *pWidget = mpParent; pWidget; pWidget = pWidget->mpParent )
445 depth++;
446 return depth;
447 }
448
449 enum PropertyKind {
450 WINDOW_PROPERTY, CONTAINER_PROPERTY, WINBITS_PROPERTY
451 };
452
findProperty(const PropList & props,rtl::OUString propName)453 static rtl::OUString findProperty( const PropList &props, rtl::OUString propName )
454 {
455 for ( PropList::const_iterator it = props.begin(); it != props.end(); it++ )
456 if ( it->first.equalsIgnoreAsciiCase( propName ) )
457 return it->second;
458 #if DEBUG_PRINT
459 fprintf(stderr, "Serious error: property '%s' not found\n", OUSTRING_CSTR(propName));
460 #endif
461 return rtl::OUString();
462 }
463
getOriginalProperty(rtl::OUString rPropName,PropertyKind rKind)464 rtl::OUString getOriginalProperty( rtl::OUString rPropName, PropertyKind rKind )
465 {
466 rtl::OUString rValue;
467 switch ( rKind ) {
468 case WINDOW_PROPERTY:
469 rValue = findProperty( maOriProps, rPropName );
470 break;
471 case CONTAINER_PROPERTY:
472 rValue = findProperty( maOriChildProps, rPropName );
473 break;
474 case WINBITS_PROPERTY:
475 // TODO
476 break;
477 }
478
479 return rValue;
480 }
481
getProperty(rtl::OUString rPropName,PropertyKind rKind)482 rtl::OUString getProperty( rtl::OUString rPropName, PropertyKind rKind )
483 {
484 rtl::OUString rValue;
485 switch ( rKind ) {
486 case WINDOW_PROPERTY:
487 rValue = anyToString( layoutimpl::prophlp::getProperty( mxWidget, rPropName ) );
488 break;
489 case CONTAINER_PROPERTY:
490 if ( mpParent )
491 rValue = anyToString( layoutimpl::prophlp::getProperty(
492 mpParent->mxContainer->getChildProperties( mxWidget ), rPropName ) );
493 break;
494 case WINBITS_PROPERTY:
495 // TODO
496 break;
497 }
498
499 return rValue;
500 }
501
isPropertyTouched(rtl::OUString propName,PropertyKind rKind)502 bool isPropertyTouched( rtl::OUString propName, PropertyKind rKind )
503 {
504 rtl::OUString oriValue = getOriginalProperty( propName, rKind );
505 rtl::OUString newValue = getProperty( propName, rKind );
506 bool isTouched = oriValue != newValue;
507 #if DEBUG_PRINT
508 fprintf(stderr, "is property '%s' touched? %s (%s vs %s)\n", OUSTRING_CSTR(propName), isTouched ? "yes" : "no", OUSTRING_CSTR(oriValue), OUSTRING_CSTR(newValue));
509 #endif
510 return isTouched;
511 }
512
513 using LayoutWidget::setProperty;
514
setProperty(rtl::OUString rPropName,PropertyKind rKind,uno::Any rValue)515 void setProperty( rtl::OUString rPropName, PropertyKind rKind, uno::Any rValue )
516 {
517 switch ( rKind ) {
518 case WINDOW_PROPERTY:
519 layoutimpl::prophlp::setProperty( mxWidget, rPropName, rValue );
520 break;
521 case CONTAINER_PROPERTY:
522 if ( mpParent )
523 layoutimpl::prophlp::setProperty(
524 mpParent->mxContainer->getChildProperties( mxWidget ), rPropName, rValue );
525 break;
526 case WINBITS_PROPERTY:
527 // TODO
528 break;
529 }
530 }
531
532 struct PropertyIterator {
533 friend class Widget;
534 PropertyKind mrKind;
535 uno::Sequence< beans::Property > maProps;
536 int nPropIt;
537
PropertyIteratorWidget::PropertyIterator538 PropertyIterator( Widget *pWidget, PropertyKind rKind )
539 : mrKind( rKind ), nPropIt( 0 )
540 {
541 switch ( rKind )
542 {
543 case WINDOW_PROPERTY:
544 if ( layoutimpl::prophlp::canHandleProps( pWidget->mxWidget ) )
545 {
546 uno::Reference< beans::XPropertySetInfo > xInfo
547 = layoutimpl::prophlp::queryPropertyInfo( pWidget->mxWidget );
548 if ( !xInfo.is() )
549 return;
550
551 maProps = xInfo->getProperties();
552 }
553 break;
554 case CONTAINER_PROPERTY:
555 if ( pWidget->mpParent )
556 {
557 uno::Reference< beans::XPropertySet >xParentSet(
558 pWidget->mpParent->mxContainer->getChildProperties( pWidget->mxWidget ) );
559 if ( xParentSet.is())
560 {
561 uno::Reference< beans::XPropertySetInfo > xInfo( xParentSet->getPropertySetInfo() );
562 if ( xInfo.is() )
563 maProps = xInfo->getProperties();
564 }
565 }
566 break;
567 case WINBITS_PROPERTY:
568 // TODO
569 break;
570 }
571 }
572
hasNextWidget::PropertyIterator573 bool hasNext()
574 {
575 return nPropIt < maProps.getLength();
576 }
577
nextWidget::PropertyIterator578 beans::Property next()
579 {
580 /* rtl::OUString propName, propValue;
581 propName = maProps[ nPropIt ];
582 propValue = getProperty( propName, mrKind, false);
583 nPropIt++;
584 return std::pair< rtl::OUString, rtl::OUString > propPair( propName, propValue );*/
585 return maProps[ nPropIt++ ];
586 }
587 };
588 };
589
590 class EditorRoot : public layoutimpl::LayoutRoot {
591 Widget *mpParent;
592
593 public:
EditorRoot(const uno::Reference<lang::XMultiServiceFactory> & xFactory,Widget * pParent)594 EditorRoot( const uno::Reference< lang::XMultiServiceFactory >& xFactory,
595 Widget *pParent )
596 : layoutimpl::LayoutRoot( xFactory ), mpParent( pParent )
597 {
598 }
599
600 // generation
create(rtl::OUString id,const rtl::OUString unoName,long attrbs,uno::Reference<awt::XLayoutContainer> xParent)601 virtual layoutimpl::LayoutWidget *create( rtl::OUString id, const rtl::OUString unoName,
602 long attrbs, uno::Reference< awt::XLayoutContainer > xParent )
603 {
604 if ( unoName.compareToAscii( "dialog" ) == 0 )
605 return mpParent;
606
607 // TODO: go through specs to map unoName to a more human-readable label
608 Widget *pWidget = new Widget( id, mxToolkit, xParent, unoName, attrbs );
609 if ( !mxWindow.is() )
610 mxWindow = uno::Reference< awt::XWindow >( pWidget->getPeer(), uno::UNO_QUERY );
611
612 if ( pWidget->mxContainer.is() )
613 pWidget->mxContainer->setLayoutUnit( mpParent->mxContainer->getLayoutUnit() );
614
615 return pWidget;
616 }
617 };
618
619 /* Working with the layout in 1D, as if it was a flat list. */
620 namespace FlatLayout
621 {
next(Widget * pWidget)622 Widget *next( Widget *pWidget )
623 {
624 Widget *pNext;
625 pNext = pWidget->down();
626 if ( pNext ) return pNext;
627 pNext = pWidget->next();
628 if ( pNext ) return pNext;
629 for ( Widget *pUp = pWidget->up(); pUp != NULL; pUp = pUp->up() )
630 if ( (pNext = pUp->next()) != NULL )
631 return pNext;
632 return NULL;
633 }
634
635 /*
636 Widget *prev( Widget *pWidget )
637 {
638 Widget *pPrev;
639 pPrev = pWidget->prev();
640 if ( !pPrev )
641 return pWidget->up();
642
643 Widget *pBottom = pPrev->down();
644 if ( pBottom )
645 {
646 while ( pBottom->down() || pBottom->next() )
647 {
648 for ( Widget *pNext = pBottom->next(); pNext; pNext = pNext->next() )
649 pBottom = pNext;
650 Widget *pDown = pBottom->down();
651 if ( pDown )
652 pBottom = pDown;
653 }
654 return pBottom;
655 }
656 return pPrev;
657 }
658 */
659
moveWidget(Widget * pWidget,bool up)660 bool moveWidget( Widget *pWidget, bool up /*or down*/ )
661 {
662 // Keep child parent&pos for in case of failure
663 Widget *pOriContainer = pWidget->up();
664 unsigned int oriChildPos = pOriContainer->getChildPos( pWidget );
665
666 // Get parent&sibling before removing it, since relations get cut
667 Widget *pSibling = up ? pWidget->prev() : pWidget->next();
668 Widget *pContainer = pWidget->up();
669 if ( !pContainer )
670 return false;
671
672 // try to swap with parent or child
673 // We need to allow for this at least for the root node...
674 if ( !pSibling )
675 {
676 if ( up )
677 {
678 if ( pContainer->swapWithChild( pWidget ) )
679 return true;
680 }
681 else
682 {
683 // TODO: this is a nice feature, but we probably want to do it explicitely...
684 #if 0
685 if ( pWidget->down() && pWidget->swapWithChild( pWidget->down() ) )
686 return true;
687 #endif
688 }
689 }
690
691 pContainer->removeChild( pWidget );
692
693 // if has up sibling -- append to it, else swap with it
694 if ( pSibling )
695 {
696 if ( pSibling->addChild( pWidget, up ? 0xffff : 0 ) )
697 return true;
698
699 unsigned int childPos = pContainer->getChildPos( pSibling );
700 if ( pContainer->addChild( pWidget, childPos + (up ? 0 : 1) ) )
701 return true; // should always be succesful
702 }
703 // go through parents -- try to get prepended to them
704 else
705 {
706 for ( ; pContainer && pContainer->up(); pContainer = pContainer->up() )
707 {
708 unsigned int childPos = pContainer->up()->getChildPos( pContainer );
709 if ( pContainer->up()->addChild( pWidget, childPos + (up ? 0 : 1) ) )
710 return true;
711 }
712 }
713
714 // failed -- try to get it to its old position
715 if ( !pOriContainer->addChild( pWidget, oriChildPos ) )
716 {
717 // a parent should never reject a child back. but if it ever
718 // happens, just kill it, we don't run an orphanate here ;P
719 delete pWidget;
720 return true;
721 }
722 return false;
723 }
724
725 // NOTE: root is considered to be number -1
get(Widget * pRoot,int nb)726 Widget *get( Widget *pRoot, int nb )
727 {
728 Widget *it;
729 for ( it = pRoot; it != NULL && nb >= 0; it = next( it ) )
730 nb--;
731 return it;
732 }
733
get(Widget * pRoot,Widget * pWidget)734 int get( Widget *pRoot, Widget *pWidget )
735 {
736 int nRet = -1;
737 Widget *it;
738 for ( it = pRoot; it != NULL && it != pWidget; it = next( it ) )
739 nRet++;
740 return nRet;
741 }
742 }
743
744 //** PropertiesList widget
745
746 class PropertiesList : public layout::Table
747 {
748 class PropertyEntry
749 {
750 friend class PropertiesList;
751
752 /* wrapper between the widget and Any */
753 struct AnyWidget
754 {
755 DECL_LINK( ApplyPropertyHdl, layout::Window* );
756 DECL_LINK( FlagToggledHdl, layout::CheckBox* );
757
AnyWidgetPropertiesList::PropertyEntry::AnyWidget758 AnyWidget( Widget *pWidget, rtl::OUString aPropName, Widget::PropertyKind aPropKind )
759 : mpWidget( pWidget ), maPropName( aPropName ), maPropKind( aPropKind )
760 {
761 mpFlag = 0;
762 mbBlockFlagCallback = false;
763 bFirstGet = true;
764 }
765
~AnyWidgetPropertiesList::PropertyEntry::AnyWidget766 virtual ~AnyWidget()
767 {
768 #if DEBUG_PRINT
769 fprintf(stderr, "~AnyWidget\n");
770 #endif
771 }
772
savePropertiesList::PropertyEntry::AnyWidget773 void save( uno::Any aValue )
774 {
775 mpWidget->setProperty( maPropName, maPropKind, aValue );
776 checkProperty();
777 }
778
checkPropertyPropertiesList::PropertyEntry::AnyWidget779 void checkProperty()
780 {
781 bool flag = mpWidget->isPropertyTouched( maPropName, maPropKind );
782
783 if ( mpFlag && mpFlag->IsChecked() != (BOOL)flag )
784 {
785 CheckFlag( flag, true );
786 }
787 }
788
CheckFlagPropertiesList::PropertyEntry::AnyWidget789 void CheckFlag( bool bValue, bool bBlockCallback )
790 {
791 if ( bBlockCallback )
792 mbBlockFlagCallback = true;
793 mpFlag->Check( bValue );
794 mbBlockFlagCallback = false;
795 }
796
797 bool bFirstGet; // HACK
getValuePropertiesList::PropertyEntry::AnyWidget798 rtl::OUString getValue()
799 {
800 // return mpWidget->getOriProperty( maPropName );
801 rtl::OUString value;
802 if ( bFirstGet ) // king of ugliness
803 value = mpWidget->getProperty( maPropName, maPropKind );
804 else
805 value = mpWidget->getOriginalProperty( maPropName, maPropKind );
806 bFirstGet = false;
807 return value;
808 }
809
810 // FIXME: wrapper should have a base class for this...
811 virtual layout::Window *getWindow() = 0;
getContainerPropertiesList::PropertyEntry::AnyWidget812 virtual layout::Container *getContainer() { return NULL; }
813
814 virtual void load() = 0;
815 virtual void store() = 0;
816
817 Widget *mpWidget;
818 rtl::OUString maPropName;
819 Widget::PropertyKind maPropKind;
820 layout::CheckBox *mpFlag;
821 bool mbBlockFlagCallback;
822 };
823
824 struct AnyEdit : public AnyWidget, layout::HBox
825 {
826 layout::Edit *mpEdit;
827 bool mbMultiLine;
828 layout::PushButton *mpExpand;
829 DECL_LINK( ExpandEditHdl, layout::PushButton* );
830
831 // so we can create widgets (like transforming the Edit into a
832 // MultiLineEdit)
833 layout::Window *mpWinParent;
834
AnyEditPropertiesList::PropertyEntry::AnyEdit835 AnyEdit( Widget *pWidget, rtl::OUString aPropName,
836 Widget::PropertyKind aPropKind, layout::Window *pWinParent )
837 : AnyWidget( pWidget, aPropName, aPropKind ), layout::HBox( 0, false ), mpWinParent( pWinParent )
838 {
839 mpEdit = NULL;
840 mpExpand = new layout::PushButton( pWinParent, WB_TOGGLE );
841 mpExpand->SetToggleHdl( LINK( this, AnyEdit, ExpandEditHdl ) );
842 setAsMultiLine( false );
843
844 load();
845 }
846
~AnyEditPropertiesList::PropertyEntry::AnyEdit847 virtual ~AnyEdit()
848 {
849 delete mpEdit;
850 delete mpExpand;
851 }
852
getWindowPropertiesList::PropertyEntry::AnyEdit853 virtual layout::Window *getWindow()
854 { return NULL; }
getContainerPropertiesList::PropertyEntry::AnyEdit855 virtual layout::Container *getContainer()
856 { return this; }
857
setAsMultiLinePropertiesList::PropertyEntry::AnyEdit858 void setAsMultiLine( bool bMultiLine )
859 {
860 Clear();
861 XubString text;
862 if ( mpEdit )
863 {
864 text = mpEdit->GetText();
865 printf("Remove mpEdit and expand\n");
866 Remove( mpEdit );
867 Remove( mpExpand );
868 delete mpEdit;
869 }
870
871 if ( bMultiLine )
872 {
873 mpEdit = new layout::Edit( mpWinParent, WB_BORDER );
874 mpExpand->SetText( String::CreateFromAscii( "-" ) );
875 }
876 else
877 {
878 mpEdit = new layout::Edit( mpWinParent, WB_BORDER );
879 mpExpand->SetText( String::CreateFromAscii( "+" ) );
880 }
881
882 mpEdit->SetText( text );
883 mpEdit->SetModifyHdl( LINK( this, AnyEdit, ApplyPropertyHdl ) );
884
885 Add( mpEdit, true, true, 0 );
886 Add( mpExpand, false, true, 0 );
887
888 mbMultiLine = bMultiLine;
889 }
890
891 #if 0
892 // TODO: make this global... We'll likely need it for export...
893 struct Translate {
894 const char *ori, *dest;
895 };
896 static rtl::OUString stringReplace( rtl::OUString _str,
897 Translate *trans )
898 {
899 const sal_Unicode *str = _str.getStr();
900 rtl::OUStringBuffer buf;
901 int i, j, k;
902 for ( i = 0; i < _str.getLength(); i++ )
903 {
904 for ( j = 0; trans[ j ].ori; j++ )
905 {
906 const char *ori = trans[ j ].ori;
907 for ( k = 0; ori[ k ] && i+k < _str.getLength(); k++ )
908 if ( ori[ k ] != str[ i+k ] )
909 break;
910 if ( !ori[ k ] )
911 {
912 // found substring
913 buf.appendAscii( trans[ j ].dest );
914 i += k;
915 continue;
916 }
917 }
918 buf.append( str[ i ] );
919 }
920 return buf.makeStringAndClear();
921 }
922 #endif
923
loadPropertiesList::PropertyEntry::AnyEdit924 virtual void load()
925 {
926 #if 0
927 // replace end of lines by "\\n" strings
928 Translate trans[] = {
929 { "\\", "\\\\" }, { "\n", "\\n" }, { 0, 0 }
930 };
931 rtl::OUString str = anyToString( getValue() );
932 str = stringReplace( str, trans );
933 SetText( str );
934 #endif
935 mpEdit->SetText( getValue() );
936 checkProperty();
937 }
938
storePropertiesList::PropertyEntry::AnyEdit939 virtual void store()
940 {
941 #if 0
942 // replace "\\n" strings by actual end of lines
943 Translate trans[] = {
944 { "\\\\", "\\" }, { "\\n", "\n" },
945 { "\\", "" }, { 0, 0 }
946 };
947 rtl::OUString str = GetText();
948 str = stringReplace( str, trans );
949 save( uno::makeAny( str ) );
950 #endif
951 save( uno::makeAny( (rtl::OUString) mpEdit->GetText() ) );
952 }
953 };
954
955 struct AnyInteger : public AnyWidget, NumericField
956 {
AnyIntegerPropertiesList::PropertyEntry::AnyInteger957 AnyInteger( Widget *pWidget, rtl::OUString aPropName,
958 Widget::PropertyKind aPropKind, Window *pWinParent )
959 : AnyWidget( pWidget, aPropName, aPropKind ), NumericField( pWinParent, WB_SPIN|WB_BORDER )
960 {
961 load();
962 SetModifyHdl( LINK( this, AnyInteger, ApplyPropertyHdl ) );
963 }
964
getWindowPropertiesList::PropertyEntry::AnyInteger965 virtual Window *getWindow()
966 { return this; }
967
loadPropertiesList::PropertyEntry::AnyInteger968 virtual void load()
969 {
970 OUString text = getValue();
971 SetText( text.getStr() );
972 checkProperty();
973 }
974
storePropertiesList::PropertyEntry::AnyInteger975 virtual void store()
976 {
977 #if DEBUG_PRINT
978 fprintf(stderr, "store number: %ld\n", rtl::OUString( GetText() ).toInt64());
979 #endif
980 save( uno::makeAny( rtl::OUString( GetText() ).toInt64() ) );
981 }
982 };
983
984 struct AnyFloat : public AnyInteger
985 {
AnyFloatPropertiesList::PropertyEntry::AnyFloat986 AnyFloat( Widget *pWidget, rtl::OUString aPropName,
987 Widget::PropertyKind aPropKind, Window *pWinParent )
988 : AnyInteger( pWidget, aPropName, aPropKind, pWinParent )
989 {}
990
storePropertiesList::PropertyEntry::AnyFloat991 virtual void store()
992 {
993 save( uno::makeAny( rtl::OUString( GetText() ).toDouble() ) );
994 }
995 };
996
997 struct AnyCheckBox : public AnyWidget, layout::CheckBox
998 {
AnyCheckBoxPropertiesList::PropertyEntry::AnyCheckBox999 AnyCheckBox( Widget *pWidget, rtl::OUString aPropName,
1000 Widget::PropertyKind aPropKind, layout::Window *pWinParent )
1001 : AnyWidget( pWidget, aPropName, aPropKind ), layout::CheckBox( pWinParent )
1002 {
1003 // adding some whitespaces to make the hit area larger
1004 // SetText( String::CreateFromAscii( "" ) );
1005 load();
1006 SetToggleHdl( LINK( this, AnyWidget, ApplyPropertyHdl ) );
1007 }
1008
~AnyCheckBoxPropertiesList::PropertyEntry::AnyCheckBox1009 virtual ~AnyCheckBox()
1010 {
1011 #if DEBUG_PRINT
1012 fprintf(stderr, "~AnyCheckBox\n");
1013 #endif
1014 }
1015
getWindowPropertiesList::PropertyEntry::AnyCheckBox1016 virtual layout::Window *getWindow()
1017 { return this; }
1018
loadPropertiesList::PropertyEntry::AnyCheckBox1019 virtual void load()
1020 {
1021 #if DEBUG_PRINT
1022 fprintf(stderr, "loading boolean value\n");
1023 #endif
1024 Check( getValue().toInt64() != 0 );
1025 setLabel();
1026 checkProperty();
1027 }
1028
storePropertiesList::PropertyEntry::AnyCheckBox1029 virtual void store()
1030 {
1031 save( uno::makeAny( IsChecked() ) );
1032 setLabel();
1033 }
1034
setLabelPropertiesList::PropertyEntry::AnyCheckBox1035 void setLabel()
1036 {
1037 SetText( String::CreateFromAscii( IsChecked() ? "true" : "false" ) );
1038 }
1039 };
1040
1041 struct AnyListBox : public AnyWidget, layout::ListBox
1042 {
AnyListBoxPropertiesList::PropertyEntry::AnyListBox1043 AnyListBox( Widget *pWidget, rtl::OUString aPropName,
1044 Widget::PropertyKind aPropKind, Window *pWinParent )
1045 : AnyWidget( pWidget, aPropName, aPropKind ), layout::ListBox( pWinParent, WB_DROPDOWN )
1046 {
1047 SetSelectHdl( LINK( this, AnyWidget, ApplyPropertyHdl ) );
1048 }
1049
getWindowPropertiesList::PropertyEntry::AnyListBox1050 virtual layout::Window *getWindow()
1051 { return this; }
1052
loadPropertiesList::PropertyEntry::AnyListBox1053 virtual void load()
1054 {
1055 SelectEntryPos( sal::static_int_cast< USHORT >( getValue().toInt32() ) );
1056 checkProperty();
1057 }
1058
storePropertiesList::PropertyEntry::AnyListBox1059 virtual void store()
1060 {
1061 save( uno::makeAny( (short) GetSelectEntryPos() ) );
1062 }
1063 };
1064
1065 struct AnyAlign : public AnyListBox
1066 {
AnyAlignPropertiesList::PropertyEntry::AnyAlign1067 AnyAlign( Widget *pWidget, rtl::OUString aPropName,
1068 Widget::PropertyKind aPropKind, Window *pWinParent )
1069 : AnyListBox( pWidget, aPropName, aPropKind, pWinParent )
1070 {
1071 InsertEntry( XubString::CreateFromAscii( "Left" ) );
1072 InsertEntry( XubString::CreateFromAscii( "Center" ) );
1073 InsertEntry( XubString::CreateFromAscii( "Right" ) );
1074 load();
1075 }
1076 };
1077
1078 /* AnyListBox and AnyComboBox different in that a ComboBox allows the user
1079 to add other options, operating in strings, instead of constants.
1080 (its more like a suggestive AnyEdit) */
1081 struct AnyComboBox : public AnyWidget, layout::ComboBox
1082 {
AnyComboBoxPropertiesList::PropertyEntry::AnyComboBox1083 AnyComboBox( Widget *pWidget, rtl::OUString aPropName,
1084 Widget::PropertyKind aPropKind, Window *pWinParent )
1085 : AnyWidget( pWidget, aPropName, aPropKind ), layout::ComboBox( pWinParent, WB_DROPDOWN )
1086 {
1087 SetModifyHdl( LINK( this, AnyComboBox, ApplyPropertyHdl ) );
1088 }
1089
getWindowPropertiesList::PropertyEntry::AnyComboBox1090 virtual layout::Window *getWindow()
1091 { return this; }
1092
loadPropertiesList::PropertyEntry::AnyComboBox1093 virtual void load()
1094 {
1095 SetText( getValue() );
1096 checkProperty();
1097 }
1098
storePropertiesList::PropertyEntry::AnyComboBox1099 virtual void store()
1100 {
1101 save( uno::makeAny( (rtl::OUString) GetText() ) );
1102 }
1103 };
1104
1105 struct AnyFontStyle : public AnyComboBox
1106 {
AnyFontStylePropertiesList::PropertyEntry::AnyFontStyle1107 AnyFontStyle( Widget *pWidget, rtl::OUString aPropName,
1108 Widget::PropertyKind aPropKind, Window *pWinParent )
1109 : AnyComboBox( pWidget, aPropName, aPropKind, pWinParent )
1110 {
1111 InsertEntry( XubString::CreateFromAscii( "Bold" ) );
1112 InsertEntry( XubString::CreateFromAscii( "Italic" ) );
1113 InsertEntry( XubString::CreateFromAscii( "Bold Italic" ) );
1114 InsertEntry( XubString::CreateFromAscii( "Fett" ) );
1115 load();
1116 }
1117 };
1118
1119 layout::FixedText *mpLabel;
1120 layout::CheckBox *mpFlag;
1121 AnyWidget *mpValue;
1122
1123 public:
PropertyEntry(layout::Window * pWinParent,AnyWidget * pAnyWidget)1124 PropertyEntry( layout::Window *pWinParent, AnyWidget *pAnyWidget )
1125 {
1126 mpLabel = new layout::FixedText( pWinParent );
1127 {
1128 // append ':' to aPropName
1129 rtl::OUStringBuffer buf( pAnyWidget->maPropName );
1130 buf.append( sal_Unicode (':') );
1131 mpLabel->SetText( buf.makeStringAndClear() );
1132 }
1133 mpValue = pAnyWidget;
1134 mpFlag = new layout::CheckBox( pWinParent );
1135 mpFlag->SetToggleHdl( LINK( mpValue, AnyWidget, FlagToggledHdl ) );
1136 mpValue->mpFlag = mpFlag;
1137 }
1138
~PropertyEntry()1139 ~PropertyEntry()
1140 {
1141 #if DEBUG_PRINT
1142 fprintf(stderr, "REMOVING label, flag and value\n");
1143 #endif
1144 delete mpLabel;
1145 delete mpFlag;
1146 delete mpValue;
1147 }
1148
1149 // Use this factory rather than the constructor -- check for NULL
construct(Widget * pWidget,rtl::OUString aPropName,Widget::PropertyKind aPropKind,sal_uInt16 nType,layout::Window * pWinParent)1150 static PropertyEntry *construct( Widget *pWidget, rtl::OUString aPropName,
1151 Widget::PropertyKind aPropKind, sal_uInt16 nType,
1152 layout::Window *pWinParent )
1153 {
1154 AnyWidget *pAnyWidget;
1155 switch (nType) {
1156 case uno::TypeClass_STRING:
1157 if ( aPropName.compareToAscii( "FontStyleName" ) == 0 )
1158 {
1159 pAnyWidget = new AnyFontStyle( pWidget, aPropName, aPropKind, pWinParent );
1160 break;
1161 }
1162 pAnyWidget = new AnyEdit( pWidget, aPropName, aPropKind, pWinParent );
1163 break;
1164 case uno::TypeClass_SHORT:
1165 if ( aPropName.compareToAscii( "Align" ) == 0 )
1166 {
1167 pAnyWidget = new AnyAlign( pWidget, aPropName, aPropKind, pWinParent );
1168 break;
1169 }
1170 // otherwise, treat as any other number...
1171 case uno::TypeClass_LONG:
1172 case uno::TypeClass_UNSIGNED_LONG:
1173 pAnyWidget = new AnyInteger( pWidget, aPropName, aPropKind, pWinParent );
1174 break;
1175 case uno::TypeClass_FLOAT:
1176 case uno::TypeClass_DOUBLE:
1177 pAnyWidget = new AnyFloat( pWidget, aPropName, aPropKind, pWinParent );
1178 break;
1179 case uno::TypeClass_BOOLEAN:
1180 pAnyWidget = new AnyCheckBox( pWidget, aPropName, aPropKind, pWinParent );
1181 break;
1182 default:
1183 return NULL;
1184 }
1185 return new PropertyEntry( pWinParent, pAnyWidget );
1186 }
1187 };
1188
1189 layout::Window *mpParentWindow;
1190
1191 std::list< PropertyEntry* > maPropertiesList;
1192 layout::FixedLine *mpSeparator;
1193
1194 // some properties are obscure, or simply don't make sense in this
1195 // context. Let's just ignore them.
1196 // Maybe we could offer them in an expander or something...
toIgnore(rtl::OUString prop)1197 static bool toIgnore( rtl::OUString prop )
1198 {
1199 // binary search -- keep the list sorted alphabetically
1200 static char const *toIgnoreList[] = {
1201 "DefaultControl", "FocusOnClick", "FontCharWidth", "FontCharset",
1202 "FontEmphasisMark", "FontFamily", "FontHeight", "FontKerning", "FontName",
1203 "FontOrientation", "FontPitch", "FontRelief", "FontSlant", "FontStrikeout",
1204 "FontType", "FontWordLineMode", "HelpText", "HelpURL", "MultiLine",
1205 "Printable", "Repeat", "RepeatDelay", "Tabstop"
1206 };
1207
1208 #if 0
1209 // checks list sanity -- enable this when you add some entries...
1210 for ( unsigned int i = 1; i < sizeof( toIgnoreList )/sizeof( char * ); i++ )
1211 {
1212 if ( strcmp(toIgnoreList[i-1], toIgnoreList[i]) >= 0 )
1213 {
1214 printf("ignore list not ordered properly: "
1215 "'%s' should come before '%s'\n",
1216 toIgnoreList[i], toIgnoreList[i-1]);
1217 exit(-1);
1218 }
1219 }
1220 #endif
1221
1222 int min = 0, max = sizeof( toIgnoreList )/sizeof( char * ) - 1, mid, cmp;
1223 do {
1224 mid = min + (max - min)/2;
1225 cmp = prop.compareToAscii( toIgnoreList[ mid ] );
1226 if ( cmp > 0 )
1227 min = mid+1;
1228 else if ( cmp < 0 )
1229 max = mid-1;
1230 else
1231 return true;
1232 } while ( min <= max );
1233 return false;
1234 }
1235
1236 public:
PropertiesList(layout::Dialog * dialog)1237 PropertiesList( layout::Dialog *dialog )
1238 : layout::Table( dialog, "properties-box" )
1239 , mpParentWindow( dialog ), mpSeparator( 0 )
1240 {
1241 }
1242
~PropertiesList()1243 ~PropertiesList()
1244 {
1245 clear();
1246 }
1247
1248 private:
1249 // auxiliary, add properties from the peer to the list
addProperties(Widget * pWidget,Widget::PropertyKind rKind)1250 void addProperties( Widget *pWidget, Widget::PropertyKind rKind )
1251 {
1252 Widget::PropertyIterator it( pWidget, rKind );
1253 while ( it.hasNext() )
1254 {
1255 beans::Property prop = it.next();
1256 rtl::OUString name( prop.Name );
1257 if ( toIgnore( name ) )
1258 continue;
1259 sal_uInt16 type = static_cast< sal_uInt16 >( prop.Type.getTypeClass() );
1260
1261 PropertyEntry *propEntry = PropertyEntry::construct(
1262 pWidget, name, rKind, type, mpParentWindow );
1263
1264 if ( propEntry )
1265 {
1266 Add( propEntry->mpLabel, false, false );
1267
1268 // HACK: one of these will return Null...
1269 Add( propEntry->mpValue->getWindow(), true, false );
1270 Add( propEntry->mpValue->getContainer(), true, false );
1271
1272 Add( propEntry->mpFlag, false, false );
1273 maPropertiesList.push_back( propEntry );
1274 }
1275 }
1276 }
1277
1278 public:
selectedWidget(Widget * pWidget)1279 void selectedWidget( Widget *pWidget )
1280 {
1281 clear();
1282
1283 if ( !pWidget )
1284 return;
1285
1286 addProperties( pWidget, Widget::CONTAINER_PROPERTY );
1287
1288 mpSeparator = new layout::FixedLine( mpParentWindow );
1289 // TODO: we may want to have to separate list widgets here...
1290 Add( mpSeparator, false, false, 3, 1 );
1291
1292 addProperties( pWidget, Widget::WINDOW_PROPERTY );
1293
1294 ShowAll( true );
1295 }
1296
clear()1297 void clear()
1298 {
1299 ///FIXME: crash
1300 Container::Clear();
1301
1302 for ( std::list< PropertyEntry* >::iterator it = maPropertiesList.begin();
1303 it != maPropertiesList.end(); it++)
1304 delete *it;
1305 maPropertiesList.clear();
1306
1307 delete mpSeparator;
1308 mpSeparator = NULL;
1309 }
1310 };
1311
IMPL_LINK(PropertiesList::PropertyEntry::AnyWidget,ApplyPropertyHdl,layout::Window *,pWin)1312 IMPL_LINK( PropertiesList::PropertyEntry::AnyWidget, ApplyPropertyHdl, layout::Window *, pWin )
1313 {
1314 (void) pWin;
1315 store();
1316 return 0;
1317 }
1318
IMPL_LINK(PropertiesList::PropertyEntry::AnyWidget,FlagToggledHdl,layout::CheckBox *,pCheck)1319 IMPL_LINK( PropertiesList::PropertyEntry::AnyWidget, FlagToggledHdl, layout::CheckBox *, pCheck )
1320 {
1321 #if DEBUG_PRINT
1322 fprintf(stderr, "Property flag pressed -- is: %d\n", pCheck->IsChecked());
1323 #endif
1324 if ( !mbBlockFlagCallback )
1325 {
1326 bool checked = pCheck->IsChecked();
1327 if ( !checked ) // revert
1328 {
1329 #if DEBUG_PRINT
1330 fprintf(stderr, "revert\n");
1331 #endif
1332 load();
1333 }
1334 else
1335 {
1336 #if DEBUG_PRINT
1337 fprintf(stderr, "user can't dirty the flag!\n");
1338 #endif
1339 // User can't flag the property as dirty
1340 // Actually, we may want to allow the designer to force a property to be stored.
1341 // Could be useful when the default value of some new property wasn't yet decided...
1342 CheckFlag( false, true );
1343 }
1344 }
1345 #if DEBUG_PRINT
1346 else
1347 fprintf(stderr, "Property flag pressed -- BLOCKED\n");
1348 #endif
1349 return 0;
1350 }
1351
IMPL_LINK(PropertiesList::PropertyEntry::AnyEdit,ExpandEditHdl,layout::PushButton *,pBtn)1352 IMPL_LINK( PropertiesList::PropertyEntry::AnyEdit, ExpandEditHdl, layout::PushButton *, pBtn )
1353 {
1354 setAsMultiLine( pBtn->IsChecked() );
1355 return 0;
1356 }
1357
1358 //** SortListBox auxiliary widget
1359
1360 class SortListBox
1361 { // For a manual sort ListBox; asks for a ListBox and Up/Down/Remove
1362 // buttons to wrap
1363 DECL_LINK( ItemSelectedHdl, layout::ListBox* );
1364 DECL_LINK( UpPressedHdl, layout::Button* );
1365 DECL_LINK( DownPressedHdl, layout::Button* );
1366 DECL_LINK( RemovePressedHdl, layout::Button* );
1367 layout::PushButton *mpUpButton, *mpDownButton, *mpRemoveButton;
1368
1369 protected:
1370 layout::ListBox *mpListBox;
1371
upPressed(USHORT nPos)1372 virtual void upPressed( USHORT nPos )
1373 {
1374 XubString str = mpListBox->GetSelectEntry();
1375 mpListBox->RemoveEntry( nPos );
1376 nPos = mpListBox->InsertEntry( str, nPos-1 );
1377 mpListBox->SelectEntryPos( nPos );
1378 }
1379
downPressed(USHORT nPos)1380 virtual void downPressed( USHORT nPos )
1381 {
1382 XubString str = mpListBox->GetSelectEntry();
1383 mpListBox->RemoveEntry( nPos );
1384 nPos = mpListBox->InsertEntry( str, nPos+1 );
1385 mpListBox->SelectEntryPos( nPos );
1386 }
1387
removePressed(USHORT nPos)1388 virtual void removePressed( USHORT nPos )
1389 {
1390 mpListBox->RemoveEntry( nPos );
1391 }
1392
itemSelected(USHORT nPos)1393 virtual void itemSelected( USHORT nPos )
1394 {
1395 // if we had some XLayoutContainer::canAdd() or maxChildren() function
1396 // we could make a function to check if we can move selected and enable/
1397 // /disable the move buttons as appropriate
1398
1399 if ( nPos == LISTBOX_ENTRY_NOTFOUND )
1400 {
1401 mpUpButton->Disable();
1402 mpDownButton->Disable();
1403 mpRemoveButton->Disable();
1404 }
1405 else
1406 {
1407 mpUpButton->Enable();
1408 mpDownButton->Enable();
1409 mpRemoveButton->Enable();
1410 }
1411 }
1412
1413 public:
SortListBox(layout::ListBox * pListBox,layout::PushButton * pUpButton,layout::PushButton * pDownButton,layout::PushButton * pRemoveButton)1414 SortListBox( layout::ListBox *pListBox, layout::PushButton *pUpButton, layout::PushButton *pDownButton,
1415 layout::PushButton *pRemoveButton )
1416 : mpUpButton( pUpButton), mpDownButton( pDownButton), mpRemoveButton( pRemoveButton ),
1417 mpListBox( pListBox )
1418 {
1419 mpListBox->SetSelectHdl( LINK( this, SortListBox, ItemSelectedHdl ) );
1420
1421 mpUpButton->SetModeImage( layout::Image ( "res/commandimagelist/lc_moveup.png" ) );
1422 mpUpButton->SetImageAlign( IMAGEALIGN_LEFT );
1423 mpUpButton->SetClickHdl( LINK( this, SortListBox, UpPressedHdl ) );
1424
1425 mpDownButton->SetModeImage( layout::Image ( "res/commandimagelist/lc_movedown.png" ) );
1426 mpDownButton->SetImageAlign( IMAGEALIGN_LEFT );
1427 mpDownButton->SetClickHdl( LINK( this, SortListBox, DownPressedHdl ) );
1428
1429 // "res/commandimagelist/lch_delete.png", "res/commandimagelist/lc_delete.png"
1430 mpRemoveButton->SetModeImage( layout::Image ( "res/commandimagelist/sc_closedoc.png" ) );
1431 mpRemoveButton->SetImageAlign( IMAGEALIGN_LEFT );
1432 mpRemoveButton->SetClickHdl( LINK( this, SortListBox, RemovePressedHdl ) );
1433
1434 // fire an un-select event
1435 itemSelected( LISTBOX_ENTRY_NOTFOUND );
1436 }
1437
1438 virtual ~SortListBox();
1439 };
1440
~SortListBox()1441 SortListBox::~SortListBox()
1442 {
1443 delete mpListBox;
1444 delete mpUpButton;
1445 delete mpDownButton;
1446 delete mpRemoveButton;
1447 }
1448
IMPL_LINK(SortListBox,UpPressedHdl,layout::Button *,pBtn)1449 IMPL_LINK( SortListBox, UpPressedHdl, layout::Button *, pBtn )
1450 {
1451 (void) pBtn;
1452 USHORT pos = mpListBox->GetSelectEntryPos();
1453 if ( pos > 0 && pos != LISTBOX_ENTRY_NOTFOUND )
1454 upPressed( pos );
1455 return 0;
1456 }
1457
IMPL_LINK(SortListBox,DownPressedHdl,layout::Button *,pBtn)1458 IMPL_LINK( SortListBox, DownPressedHdl, layout::Button *, pBtn )
1459 {
1460 (void) pBtn;
1461 USHORT pos = mpListBox->GetSelectEntryPos();
1462 if ( pos < mpListBox->GetEntryCount() && pos != LISTBOX_ENTRY_NOTFOUND )
1463 downPressed( pos );
1464 return 0;
1465 }
1466
IMPL_LINK(SortListBox,RemovePressedHdl,layout::Button *,pBtn)1467 IMPL_LINK( SortListBox, RemovePressedHdl, layout::Button *, pBtn )
1468 {
1469 (void) pBtn;
1470 USHORT pos = mpListBox->GetSelectEntryPos();
1471 if ( pos != LISTBOX_ENTRY_NOTFOUND )
1472 removePressed( pos );
1473 return 0;
1474 }
1475
IMPL_LINK(SortListBox,ItemSelectedHdl,layout::ListBox *,pList)1476 IMPL_LINK( SortListBox, ItemSelectedHdl, layout::ListBox *, pList )
1477 {
1478 (void) pList;
1479 USHORT pos = mpListBox->GetSelectEntryPos();
1480 itemSelected( pos );
1481 return 0;
1482 }
1483
1484 //** LayoutTree widget
1485
1486 class LayoutTree : public SortListBox
1487 {
1488 public:
1489 struct Listener
1490 {
1491 virtual void widgetSelected( Widget *pWidget ) = 0;
1492 };
1493
1494 private:
1495 Listener *mpListener;
1496
1497 public:
1498 Widget *mpRootWidget;
1499
LayoutTree(layout::Dialog * dialog)1500 LayoutTree( layout::Dialog *dialog )
1501 : SortListBox( new layout::ListBox( dialog, "layout-tree" ),
1502 new layout::PushButton( dialog, "layout-up-button" ),
1503 new layout::PushButton( dialog, "layout-down-button" ),
1504 new layout::PushButton( dialog, "layout-remove-button" ) )
1505 {
1506 layout::PeerHandle handle = dialog->GetPeerHandle( "preview-box" );
1507 uno::Reference< awt::XLayoutConstrains > xWidget( handle, uno::UNO_QUERY );
1508 mpRootWidget = new Widget( xWidget, "root" );
1509 }
1510
1511 virtual ~LayoutTree();
1512
getWidget(int nPos)1513 Widget *getWidget( int nPos )
1514 {
1515 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1516 return FlatLayout::get( mpRootWidget, nPos );
1517 return NULL;
1518 }
1519
getSelectedWidget()1520 Widget *getSelectedWidget()
1521 {
1522 Widget *pWidget = getWidget( mpListBox->GetSelectEntryPos() );
1523 if ( !pWidget ) // return root, if none selected
1524 pWidget = mpRootWidget;
1525 return pWidget;
1526 }
1527
selectWidget(Widget * pWidget)1528 void selectWidget( Widget *pWidget )
1529 {
1530 int pos = FlatLayout::get( mpRootWidget, pWidget );
1531 if ( pos == -1 )
1532 // if asked to select hidden root, select visible root
1533 pos = 0;
1534 mpListBox->SelectEntryPos( sal::static_int_cast< USHORT >( pos ) );
1535 }
1536
rebuild()1537 void rebuild()
1538 {
1539 struct inner
1540 {
1541 // pads a string with whitespaces
1542 static rtl::OUString padString( rtl::OUString name, int depth )
1543 {
1544 rtl::OStringBuffer aBuf( depth * 4 + name.getLength() + 2 );
1545 for (int i = 0; i < depth; i++)
1546 aBuf.append( " " );
1547 aBuf.append( rtl::OUStringToOString( name, RTL_TEXTENCODING_ASCII_US ) );
1548 return rtl::OUString( aBuf.getStr(), aBuf.getLength(),
1549 RTL_TEXTENCODING_UTF8 );
1550 }
1551 };
1552
1553 mpListBox->Clear();
1554 for ( Widget *i = FlatLayout::next( mpRootWidget ); i; i = FlatLayout::next( i ) )
1555 mpListBox->InsertEntry( inner::padString( i->getLabel(), i->getDepth()-1 ) );
1556
1557 // any selection, no longer is. ListBox doesn't fire the event on this case;
1558 // force it.
1559 itemSelected( LISTBOX_ENTRY_NOTFOUND );
1560 }
1561
setListener(Listener * pListener)1562 void setListener( Listener *pListener )
1563 { mpListener = pListener; }
1564
1565 // print in XML format...
1566
toXMLNaming(const rtl::OUString & string)1567 static rtl::OUString toXMLNaming (const rtl::OUString &string)
1568 {
1569 rtl::OUStringBuffer buffer (string.getLength());
1570 sal_Unicode *str = string.pData->buffer;
1571 for (int i = 0; i < string.getLength(); i++) {
1572 if ( str[i] >= 'A' && str[i] <= 'Z' )
1573 {
1574 if ( i > 0 )
1575 buffer.append ((sal_Unicode) '-');
1576 buffer.append ((sal_Unicode) (str[i] - 'A' + 'a'));
1577 }
1578 else
1579 buffer.append ((sal_Unicode) str[i]);
1580 }
1581
1582 return buffer.makeStringAndClear();
1583 }
1584
print()1585 void print()
1586 {
1587 printf("\t\tExport:\n");
1588 printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1589 "<dialog xmlns=\"http://openoffice.org/2007/layout\"\n"
1590 " xmlns:cnt=\"http://openoffice.org/2007/layout/container\"\n"
1591 " id=\"dialog\" title=\"Unnamed\" sizeable=\"true\" >\n");
1592
1593 for ( Widget *i = FlatLayout::next( mpRootWidget ); i; i = FlatLayout::next( i ) )
1594 {
1595 for ( int d = i->getDepth(); d > 0; d-- )
1596 printf(" ");
1597 printf("<%s ", OUSTRING_CSTR( i->getUnoName() ) );
1598
1599 for ( int kind = 0; kind < 2; kind++ )
1600 {
1601 Widget::PropertyKind wKind = kind == 0 ? Widget::WINDOW_PROPERTY
1602 : Widget::CONTAINER_PROPERTY;
1603 Widget::PropertyIterator it( i, wKind );
1604 while ( it.hasNext() )
1605 {
1606 beans::Property prop = it.next();
1607 if ( !i->isPropertyTouched( prop.Name, wKind ) )
1608 continue;
1609
1610 rtl::OUString value = i->getProperty( prop.Name, wKind );
1611 if ( prop.Type.getTypeClass() == uno::TypeClass_BOOLEAN )
1612 {
1613 if ( value.compareToAscii( "0" ) )
1614 value = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("false") );
1615 else
1616 value = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("true") );
1617 }
1618
1619 if ( value.getLength() > 0 )
1620 printf("%s%s=\"%s\" ",
1621 kind == 0 ? "" : "cnt:",
1622 OUSTRING_CSTR( toXMLNaming( prop.Name ) ), OUSTRING_CSTR( value )
1623 );
1624
1625 }
1626 }
1627 printf("/>\n");
1628 }
1629 printf("</dialog>\n");
1630 }
1631
1632 protected:
upPressed(USHORT nPos)1633 virtual void upPressed( USHORT nPos )
1634 {
1635 Widget *pWidget = getWidget( nPos );
1636 if ( FlatLayout::moveWidget( pWidget, true ) )
1637 rebuild();
1638 selectWidget( pWidget );
1639 }
1640
downPressed(USHORT nPos)1641 virtual void downPressed( USHORT nPos )
1642 {
1643 Widget *pWidget = getWidget( nPos );
1644 if ( FlatLayout::moveWidget( pWidget, false ) )
1645 rebuild();
1646 selectWidget( pWidget );
1647 }
1648
removePressed(USHORT nPos)1649 virtual void removePressed( USHORT nPos )
1650 {
1651 Widget *pWidget = getWidget( nPos );
1652 if ( pWidget )
1653 {
1654 pWidget->up()->removeChild( pWidget );
1655 delete pWidget;
1656 rebuild();
1657 }
1658 }
1659
itemSelected(USHORT nPos)1660 virtual void itemSelected( USHORT nPos )
1661 {
1662 mpListener->widgetSelected( getWidget( nPos ) );
1663 SortListBox::itemSelected( nPos );
1664 }
1665 };
1666
~LayoutTree()1667 LayoutTree::~LayoutTree()
1668 {
1669 delete mpRootWidget;
1670 }
1671
1672 //** EditorImpl
1673
1674 class EditorImpl : public LayoutTree::Listener
1675 {
1676 void createWidget( const char *unoName );
1677
1678 PropertiesList *mpPropertiesList;
1679 LayoutTree *mpLayoutTree;
1680
1681 layout::PushButton *pImportButton, *pExportButton;
1682 #ifdef FILEDLG
1683 FileDialog *pImportDialog;
1684 #endif
1685 DECL_LINK( ImportButtonHdl, layout::PushButton* );
1686 DECL_LINK( ExportButtonHdl, layout::PushButton* );
1687 #ifdef FILEDLG
1688 DECL_LINK( ImportDialogHdl, FileDialog* );
1689 #endif
1690
1691 // framework stuff
1692 uno::Reference< lang::XMultiServiceFactory > mxFactory;
1693 uno::Reference< awt::XToolkit > mxToolkit;
1694 uno::Reference< awt::XWindow > mxToplevel;
1695
1696 virtual void widgetSelected( Widget *pWidget );
1697 DECL_LINK( CreateWidgetHdl, layout::Button* );
1698
1699 std::list< layout::PushButton *> maCreateButtons;
1700
1701 public:
1702
1703 EditorImpl( layout::Dialog *dialog,
1704 // we should probable open this channel (or whatever its called) ourselves
1705 uno::Reference< lang::XMultiServiceFactory > xMSF );
1706 virtual ~EditorImpl();
1707
1708 void loadFile( const rtl::OUString &aTestFile );
1709 };
1710
EditorImpl(layout::Dialog * dialog,uno::Reference<lang::XMultiServiceFactory> xFactory)1711 EditorImpl::EditorImpl( layout::Dialog *dialog,
1712 uno::Reference< lang::XMultiServiceFactory > xFactory )
1713 : mxFactory( xFactory )
1714 , mxToplevel( dialog->GetPeerHandle( "dialog" ), uno::UNO_QUERY )
1715 // FIXME: any of these should work
1716 //dialog->getContext()->getRoot(), uno::UNO_QUERY )
1717 // dialog->GetPeer(), uno::UNO_QUERY )
1718 {
1719 #if DEBUG_PRINT
1720 fprintf (stderr, "EditorImpl()\n");
1721 #endif
1722 // framework
1723 mxToolkit = uno::Reference< awt::XToolkit >(
1724 mxFactory->createInstance(
1725 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.Toolkit" ) ) ),
1726 uno::UNO_QUERY );
1727 OSL_ASSERT( mxToolkit.is() );
1728
1729 // custom widgets
1730 #if DEBUG_PRINT
1731 fprintf (stderr, "custom widgets\n");
1732 #endif
1733 mpPropertiesList = new PropertiesList( dialog );
1734
1735 mpLayoutTree = new LayoutTree( dialog );
1736 mpLayoutTree->setListener( this );
1737
1738 /* if ( xImport.is() )
1739 mpLayoutTree->getWidget( -1 )->addChild( new Widget( xImport, "import" ) );*/
1740
1741 // create buttons
1742 layout::Container aWidgets( dialog, "create-widget" );
1743 layout::Container aContainers( dialog, "create-container" );
1744 for ( int i = 0; i < WIDGETS_SPECS_LEN; i++ )
1745 {
1746 layout::PushButton *pBtn = new layout::PushButton( (layout::Window *) dialog );
1747 pBtn->SetText( rtl::OUString::createFromAscii( WIDGETS_SPECS[ i ].pLabel ) );
1748 pBtn->SetClickHdl( LINK( this, EditorImpl, CreateWidgetHdl ) );
1749 if ( WIDGETS_SPECS[ i ].pIconName != NULL )
1750 {
1751 rtl::OString aPath ("res/commandimagelist/");
1752 aPath += WIDGETS_SPECS[ i ].pIconName;
1753 layout::Image aImg( aPath );
1754 pBtn->SetModeImage( aImg );
1755 pBtn->SetImageAlign( IMAGEALIGN_LEFT );
1756 }
1757 pBtn->Show();
1758 maCreateButtons.push_back( pBtn );
1759 layout::Container *pBox = WIDGETS_SPECS[ i ].bIsContainer ? &aContainers : &aWidgets;
1760 pBox->Add( pBtn );
1761 }
1762
1763 #ifdef FILEDLG
1764 fprintf(stderr,"creating file dialog\n");
1765 pImportDialog = new FileDialog( NULL/*(layout::Window *) dialog*/, 0 );
1766 fprintf(stderr,"connecting it\n");
1767 pImportDialog->SetFileSelectHdl( LINK( this, EditorImpl, ImportDialogHdl ) );
1768 fprintf(stderr,"done file dialog\n");
1769 #endif
1770
1771 /* pImportButton = new layout::PushButton( dialog, "import-button" );
1772 pImportButton->SetClickHdl( LINK( this, EditorImpl, ImportButtonHdl ) );*/
1773 pExportButton = new layout::PushButton( dialog, "export-button" );
1774 pExportButton->SetClickHdl( LINK( this, EditorImpl, ExportButtonHdl ) );
1775 }
1776
~EditorImpl()1777 EditorImpl::~EditorImpl()
1778 {
1779 delete mpPropertiesList;
1780 delete mpLayoutTree;
1781 for ( std::list< layout::PushButton * >::const_iterator i = maCreateButtons.begin();
1782 i != maCreateButtons.end(); i++)
1783 delete *i;
1784 delete pImportButton;
1785 delete pExportButton;
1786 #ifdef FILEDLG
1787 delete pImportDialog;
1788 #endif
1789 }
1790
loadFile(const rtl::OUString & aTestFile)1791 void EditorImpl::loadFile( const rtl::OUString &aTestFile )
1792 {
1793 fprintf( stderr, "TEST: layout instance\n" );
1794 uno::Reference< awt::XLayoutRoot > xRoot
1795 ( new EditorRoot( mxFactory, mpLayoutTree->mpRootWidget ) );
1796
1797 /*
1798 mxMSF->createInstance
1799 ( ::rtl::OUString::createFromAscii( "com.sun.star.awt.Layout" ) ),
1800 uno::UNO_QUERY );
1801 */
1802 if ( !xRoot.is() )
1803 {
1804 throw uno::RuntimeException(
1805 OUString( RTL_CONSTASCII_USTRINGPARAM("could not create awt Layout component!") ),
1806 uno::Reference< uno::XInterface >() );
1807 }
1808
1809 #if DEBUG_PRINT
1810 fprintf( stderr, "TEST: initing root\n" );
1811 #endif
1812
1813 uno::Reference< lang::XInitialization > xInit( xRoot, uno::UNO_QUERY );
1814 if ( !xInit.is() )
1815 {
1816 throw uno::RuntimeException(
1817 OUString( RTL_CONSTASCII_USTRINGPARAM("Layout has no XInitialization!") ),
1818 uno::Reference< uno::XInterface >() );
1819 }
1820
1821 #if DEBUG_PRINT
1822 fprintf( stderr, "TEST: running parser\n" );
1823 #endif
1824 uno::Sequence< uno::Any > aParams( 1 );
1825 aParams[0] <<= aTestFile;
1826 #if DEBUG_PRINT
1827 fprintf( stderr, "TEST: do it\n" );
1828 #endif
1829 xInit->initialize( aParams );
1830 #if DEBUG_PRINT
1831 fprintf( stderr, "TEST: file loaded\n" );
1832 #endif
1833
1834 mpLayoutTree->rebuild();
1835 }
1836
createWidget(const char * name)1837 void EditorImpl::createWidget( const char *name )
1838 {
1839 Widget *pWidget = mpLayoutTree->getSelectedWidget();
1840
1841 Widget *pChild = new Widget( rtl::OUString(), mxToolkit, uno::Reference< awt::XLayoutContainer >( mxToplevel, uno::UNO_QUERY ), rtl::OUString::createFromAscii( name ), awt::WindowAttribute::SHOW );
1842 if ( !pWidget->addChild( pChild ) )
1843 {
1844 delete pChild;
1845 // we may want to popup an error message
1846 }
1847 else
1848 {
1849 mpLayoutTree->rebuild();
1850 mpLayoutTree->selectWidget( pWidget );
1851 }
1852 }
1853
widgetSelected(Widget * pWidget)1854 void EditorImpl::widgetSelected( Widget *pWidget )
1855 {
1856 // we know can't add widget to a non-container, so let's disable the create
1857 // buttons then. Would be nice to have a method to check if a container is
1858 // full as well...
1859 if ( !pWidget || pWidget->isContainer() )
1860 {
1861 for ( std::list< layout::PushButton *>::const_iterator it = maCreateButtons.begin();
1862 it != maCreateButtons.end(); it++)
1863 (*it)->Enable();
1864 }
1865 else
1866 {
1867 for ( std::list< layout::PushButton *>::const_iterator it = maCreateButtons.begin();
1868 it != maCreateButtons.end(); it++)
1869 (*it)->Disable();
1870 }
1871
1872 mpPropertiesList->selectedWidget( pWidget );
1873 }
1874
IMPL_LINK(EditorImpl,CreateWidgetHdl,layout::Button *,pBtn)1875 IMPL_LINK( EditorImpl, CreateWidgetHdl, layout::Button *, pBtn )
1876 {
1877 int i = 0;
1878 for ( std::list< layout::PushButton *>::const_iterator it = maCreateButtons.begin();
1879 it != maCreateButtons.end(); it++, i++ )
1880 {
1881 if ( pBtn == *it )
1882 break;
1883 }
1884 OSL_ASSERT( i < WIDGETS_SPECS_LEN );
1885 createWidget( WIDGETS_SPECS[i].pName );
1886 return 0;
1887 }
1888
IMPL_LINK(EditorImpl,ImportButtonHdl,layout::PushButton *,pBtn)1889 IMPL_LINK( EditorImpl, ImportButtonHdl, layout::PushButton *, pBtn )
1890 {
1891 (void) pBtn;
1892 #if DEBUG_PRINT
1893 fprintf(stderr, "IMPORT!\n");
1894 #endif
1895 #ifdef FILEDLG
1896 pImportDialog->Execute();
1897 #endif
1898
1899 return 0;
1900 }
1901
1902 #ifdef FILEDLG
IMPL_LINK(EditorImpl,ImportDialogHdl,FileDialog *,pDialog)1903 IMPL_LINK( EditorImpl, ImportDialogHdl, FileDialog *, pDialog )
1904 {
1905 UniString path = pDialog->GetPath();
1906 //fprintf(stderr, "Executing import dialog!\n");
1907
1908 #if DEBUG_PRINT
1909 fprintf(stderr, "got import file: %s\n",rtl::OUStringToOString( path, RTL_TEXTENCODING_ASCII_US ).getStr() );
1910 #endif
1911
1912 return 0;
1913 }
1914 #endif
1915
IMPL_LINK(EditorImpl,ExportButtonHdl,layout::PushButton *,pBtn)1916 IMPL_LINK( EditorImpl, ExportButtonHdl, layout::PushButton *, pBtn )
1917 {
1918 (void) pBtn;
1919 mpLayoutTree->print();
1920 return 0;
1921 }
1922
1923 //** Editor, the Dialog
1924
Editor(uno::Reference<lang::XMultiServiceFactory> xFactory,rtl::OUString aFile)1925 Editor::Editor( uno::Reference< lang::XMultiServiceFactory > xFactory,
1926 rtl::OUString aFile )
1927 : layout::Dialog( (Window*) (NULL), "editor.xml", "dialog" )
1928 , mpImpl( new EditorImpl( this, xFactory ) )
1929 {
1930 if ( aFile.getLength() )
1931 mpImpl->loadFile( aFile );
1932
1933 // parent:
1934 FreeResource();
1935 }
1936
~Editor()1937 Editor::~Editor()
1938 {
1939 delete mpImpl;
1940 }
1941