1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2003 the VideoLAN team
7 * Authors: Cyril Deguet <asmax@via.ecp.fr>
8 * Olivier Teulière <ipkiss@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program 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 General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
26 #include "builder.hpp"
27 #include "builder_data.hpp"
28 #include "interpreter.hpp"
29 #include "../src/file_bitmap.hpp"
30 #include "../src/os_factory.hpp"
31 #include "../src/generic_bitmap.hpp"
32 #include "../src/top_window.hpp"
33 #include "../src/anchor.hpp"
34 #include "../src/bitmap_font.hpp"
35 #include "../src/ft2_font.hpp"
36 #include "../src/theme.hpp"
37 #include "../controls/ctrl_button.hpp"
38 #include "../controls/ctrl_checkbox.hpp"
39 #include "../controls/ctrl_image.hpp"
40 #include "../controls/ctrl_list.hpp"
41 #include "../controls/ctrl_move.hpp"
42 #include "../controls/ctrl_resize.hpp"
43 #include "../controls/ctrl_slider.hpp"
44 #include "../controls/ctrl_radialslider.hpp"
45 #include "../controls/ctrl_text.hpp"
46 #include "../controls/ctrl_tree.hpp"
47 #include "../controls/ctrl_video.hpp"
48 #include "../utils/position.hpp"
49 #include "../utils/var_bool.hpp"
50 #include "../utils/var_text.hpp"
52 #include "vlc_image.h"
55 Builder::Builder( intf_thread_t *pIntf, const BuilderData &rData,
56 const string &rPath ):
57 SkinObject( pIntf ), m_rData( rData ), m_path( rPath ), m_pTheme( NULL )
59 m_pImageHandler = image_HandlerCreate( pIntf );
64 if( m_pImageHandler ) image_HandlerDelete( m_pImageHandler );
67 CmdGeneric *Builder::parseAction( const string &rAction )
69 return Interpreter::instance( getIntf() )->parseAction( rAction, m_pTheme );
74 #define ADD_OBJECTS( type ) \
75 list<BuilderData::type>::const_iterator it##type; \
76 for( it##type = m_rData.m_list##type.begin(); \
77 it##type != m_rData.m_list##type.end(); it##type++ ) \
79 add##type( *it##type ); \
83 Theme *Builder::build()
85 m_pTheme = new Theme( getIntf() );
86 if( m_pTheme == NULL )
91 // Create everything from the data in the XML
93 ADD_OBJECTS( Bitmap );
94 ADD_OBJECTS( SubBitmap );
95 ADD_OBJECTS( BitmapFont );
97 ADD_OBJECTS( Window );
98 ADD_OBJECTS( Layout );
99 ADD_OBJECTS( Anchor );
100 ADD_OBJECTS( Button );
101 ADD_OBJECTS( Checkbox );
102 ADD_OBJECTS( Image );
104 ADD_OBJECTS( RadialSlider );
105 ADD_OBJECTS( Slider );
108 ADD_OBJECTS( Video );
114 // Macro to get a bitmap by its ID in the builder
115 #define GET_BMP( pBmp, id ) \
118 pBmp = m_pTheme->getBitmapById(id); \
121 msg_Err( getIntf(), "unknown bitmap id: %s", id.c_str() ); \
126 void Builder::addTheme( const BuilderData::Theme &rData )
128 WindowManager &rManager = m_pTheme->getWindowManager();
129 rManager.setMagnetValue( rData.m_magnet );
130 rManager.setAlphaValue( rData.m_alpha );
131 rManager.setMoveAlphaValue( rData.m_moveAlpha );
132 GenericFont *pFont = getFont( rData.m_tooltipfont );
135 rManager.createTooltip( *pFont );
139 msg_Warn( getIntf(), "Invalid tooltip font: %s",
140 rData.m_tooltipfont.c_str() );
145 void Builder::addBitmap( const BuilderData::Bitmap &rData )
147 GenericBitmap *pBmp =
148 new FileBitmap( getIntf(), m_pImageHandler,
149 getFilePath( rData.m_fileName ), rData.m_alphaColor );
150 if( !pBmp->getData() )
156 m_pTheme->m_bitmaps[rData.m_id] = GenericBitmapPtr( pBmp );
160 void Builder::addSubBitmap( const BuilderData::SubBitmap &rData )
162 if( m_pTheme->m_bitmaps.find( rData.m_id ) != m_pTheme->m_bitmaps.end() )
164 msg_Dbg( getIntf(), "Bitmap %s already exists", rData.m_id.c_str() );
168 // Get the parent bitmap
169 GenericBitmap *pParentBmp = NULL;
170 GET_BMP( pParentBmp, rData.m_parent );
172 // Copy a region of the parent bitmap to the new one
174 new BitmapImpl( getIntf(), rData.m_width, rData.m_height );
175 bool res = pBmp->drawBitmap( *pParentBmp, rData.m_x, rData.m_y, 0, 0,
176 rData.m_width, rData.m_height );
179 // Invalid sub-bitmap
181 msg_Warn( getIntf(), "SubBitmap %s ignored", rData.m_id.c_str() );
184 m_pTheme->m_bitmaps[rData.m_id] = GenericBitmapPtr( pBmp );
188 void Builder::addBitmapFont( const BuilderData::BitmapFont &rData )
190 if( m_pTheme->m_fonts.find( rData.m_id ) != m_pTheme->m_fonts.end() )
192 msg_Dbg( getIntf(), "Font %s already exists", rData.m_id.c_str() );
196 GenericBitmap *pBmp =
197 new FileBitmap( getIntf(), m_pImageHandler,
198 getFilePath( rData.m_file ), 0 );
199 if( !pBmp->getData() )
206 m_pTheme->m_bitmaps[rData.m_id] = GenericBitmapPtr( pBmp );
208 GenericFont *pFont = new BitmapFont( getIntf(), *pBmp, rData.m_type );
211 m_pTheme->m_fonts[rData.m_id] = GenericFontPtr( pFont );
220 void Builder::addFont( const BuilderData::Font &rData )
222 // Try to load the font from the theme directory
223 GenericFont *pFont = new FT2Font( getIntf(),
224 getFilePath( rData.m_fontFile ),
228 m_pTheme->m_fonts[rData.m_id] = GenericFontPtr( pFont );
234 // Font not found; try in the resource path
235 OSFactory *pOSFactory = OSFactory::instance( getIntf() );
236 const list<string> &resPath = pOSFactory->getResourcePath();
237 const string &sep = pOSFactory->getDirSeparator();
239 list<string>::const_iterator it;
240 for( it = resPath.begin(); it != resPath.end(); it++ )
242 string path = (*it) + sep + "fonts" + sep + rData.m_fontFile;
243 pFont = new FT2Font( getIntf(), path, rData.m_size );
246 // Font loaded successfully
247 m_pTheme->m_fonts[rData.m_id] = GenericFontPtr( pFont );
259 void Builder::addWindow( const BuilderData::Window &rData )
262 new TopWindow( getIntf(), rData.m_xPos, rData.m_yPos,
263 m_pTheme->getWindowManager(),
264 rData.m_dragDrop, rData.m_playOnDrop,
267 m_pTheme->m_windows[rData.m_id] = TopWindowPtr( pWin );
271 void Builder::addLayout( const BuilderData::Layout &rData )
273 TopWindow *pWin = m_pTheme->getWindowById(rData.m_windowId);
276 msg_Err( getIntf(), "unknown window id: %s", rData.m_windowId.c_str() );
280 int minWidth = rData.m_minWidth != -1 ? rData.m_minWidth : rData.m_width;
281 int maxWidth = rData.m_maxWidth != -1 ? rData.m_maxWidth : rData.m_width;
282 int minHeight = rData.m_minHeight != -1 ? rData.m_minHeight :
284 int maxHeight = rData.m_maxHeight != -1 ? rData.m_maxHeight :
286 GenericLayout *pLayout = new GenericLayout( getIntf(), rData.m_width,
288 minWidth, maxWidth, minHeight,
290 m_pTheme->m_layouts[rData.m_id] = GenericLayoutPtr( pLayout );
292 // Attach the layout to its window
293 m_pTheme->getWindowManager().addLayout( *pWin, *pLayout );
297 void Builder::addAnchor( const BuilderData::Anchor &rData )
299 GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
300 if( pLayout == NULL )
302 msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
306 Bezier *pCurve = getPoints( rData.m_points.c_str() );
309 msg_Err( getIntf(), "Invalid format in tag points=\"%s\"",
310 rData.m_points.c_str() );
313 m_pTheme->m_curves.push_back( BezierPtr( pCurve ) );
315 Anchor *pAnc = new Anchor( getIntf(), rData.m_xPos, rData.m_yPos,
316 rData.m_range, rData.m_priority,
318 pLayout->addAnchor( pAnc );
322 void Builder::addButton( const BuilderData::Button &rData )
324 // Get the bitmaps of the button
325 GenericBitmap *pBmpUp = NULL;
326 GET_BMP( pBmpUp, rData.m_upId );
328 GenericBitmap *pBmpDown = pBmpUp;
329 GET_BMP( pBmpDown, rData.m_downId );
331 GenericBitmap *pBmpOver = pBmpUp;
332 GET_BMP( pBmpOver, rData.m_overId );
334 GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
335 if( pLayout == NULL )
337 msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
341 CmdGeneric *pCommand = parseAction( rData.m_actionId );
342 if( pCommand == NULL )
344 msg_Err( getIntf(), "Invalid action: %s", rData.m_actionId.c_str() );
348 // Get the visibility variable
349 // XXX check when it is null
350 Interpreter *pInterpreter = Interpreter::instance( getIntf() );
351 VarBool *pVisible = pInterpreter->getVarBool( rData.m_visible, m_pTheme );
353 CtrlButton *pButton = new CtrlButton( getIntf(), *pBmpUp, *pBmpOver,
354 *pBmpDown, *pCommand, UString( getIntf(), rData.m_tooltip.c_str() ),
355 UString( getIntf(), rData.m_help.c_str() ), pVisible );
357 // Compute the position of the control
358 // XXX (we suppose all the images have the same size...)
359 const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
360 rData.m_xPos, rData.m_yPos,
362 pBmpUp->getHeight(), *pLayout );
364 pLayout->addControl( pButton, pos, rData.m_layer );
366 m_pTheme->m_controls[rData.m_id] = CtrlGenericPtr( pButton );
370 void Builder::addCheckbox( const BuilderData::Checkbox &rData )
372 // Get the bitmaps of the checkbox
373 GenericBitmap *pBmpUp1 = NULL;
374 GET_BMP( pBmpUp1, rData.m_up1Id );
376 GenericBitmap *pBmpDown1 = pBmpUp1;
377 GET_BMP( pBmpDown1, rData.m_down1Id );
379 GenericBitmap *pBmpOver1 = pBmpUp1;
380 GET_BMP( pBmpOver1, rData.m_over1Id );
382 GenericBitmap *pBmpUp2 = NULL;
383 GET_BMP( pBmpUp2, rData.m_up2Id );
385 GenericBitmap *pBmpDown2 = pBmpUp2;
386 GET_BMP( pBmpDown2, rData.m_down2Id );
388 GenericBitmap *pBmpOver2 = pBmpUp2;
389 GET_BMP( pBmpOver2, rData.m_over2Id );
391 GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
392 if( pLayout == NULL )
394 msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
398 CmdGeneric *pCommand1 = parseAction( rData.m_action1 );
399 if( pCommand1 == NULL )
401 msg_Err( getIntf(), "Invalid action: %s", rData.m_action1.c_str() );
405 CmdGeneric *pCommand2 = parseAction( rData.m_action2 );
406 if( pCommand2 == NULL )
408 msg_Err( getIntf(), "Invalid action: %s", rData.m_action2.c_str() );
412 // Get the state variable
413 Interpreter *pInterpreter = Interpreter::instance( getIntf() );
414 VarBool *pVar = pInterpreter->getVarBool( rData.m_state, m_pTheme );
417 // TODO: default state
421 // Get the visibility variable
422 // XXX check when it is null
423 VarBool *pVisible = pInterpreter->getVarBool( rData.m_visible, m_pTheme );
425 // Create the control
426 CtrlCheckbox *pCheckbox = new CtrlCheckbox( getIntf(), *pBmpUp1,
427 *pBmpOver1, *pBmpDown1, *pBmpUp2, *pBmpOver2, *pBmpDown2, *pCommand1,
428 *pCommand2, UString( getIntf(), rData.m_tooltip1.c_str() ),
429 UString( getIntf(), rData.m_tooltip2.c_str() ), *pVar,
430 UString( getIntf(), rData.m_help.c_str() ), pVisible );
432 // Compute the position of the control
433 // XXX (we suppose all the images have the same size...)
434 const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
435 rData.m_xPos, rData.m_yPos,
437 pBmpUp1->getHeight(), *pLayout );
439 pLayout->addControl( pCheckbox, pos, rData.m_layer );
441 m_pTheme->m_controls[rData.m_id] = CtrlGenericPtr( pCheckbox );
445 void Builder::addImage( const BuilderData::Image &rData )
447 GenericBitmap *pBmp = NULL;
448 GET_BMP( pBmp, rData.m_bmpId );
450 GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
451 if( pLayout == NULL )
453 msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
457 TopWindow *pWindow = m_pTheme->getWindowById(rData.m_windowId);
458 if( pWindow == NULL )
460 msg_Err( getIntf(), "unknown window id: %s", rData.m_windowId.c_str() );
464 CmdGeneric *pCommand = parseAction( rData.m_action2Id );
465 if( pCommand == NULL )
467 msg_Err( getIntf(), "Invalid action: %s", rData.m_action2Id.c_str() );
471 // Get the visibility variable
472 // XXX check when it is null
473 Interpreter *pInterpreter = Interpreter::instance( getIntf() );
474 VarBool *pVisible = pInterpreter->getVarBool( rData.m_visible, m_pTheme );
476 CtrlImage::resize_t resizeMethod =
477 (rData.m_resize == "scale" ? CtrlImage::kScale : CtrlImage::kMosaic);
478 CtrlImage *pImage = new CtrlImage( getIntf(), *pBmp, *pCommand,
479 resizeMethod, UString( getIntf(), rData.m_help.c_str() ), pVisible );
481 // Compute the position of the control
482 const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
484 rData.m_yPos, pBmp->getWidth(),
485 pBmp->getHeight(), *pLayout );
487 // XXX: test to be changed! XXX
488 if( rData.m_actionId == "move" )
490 CtrlMove *pMove = new CtrlMove( getIntf(), m_pTheme->getWindowManager(),
491 *pImage, *pWindow, UString( getIntf(), rData.m_help.c_str() ),
493 pLayout->addControl( pMove, pos, rData.m_layer );
495 else if( rData.m_actionId == "resizeS" )
497 CtrlResize *pResize = new CtrlResize( getIntf(), *pImage, *pLayout,
498 UString( getIntf(), rData.m_help.c_str() ), NULL,
499 CtrlResize::kResizeS );
500 pLayout->addControl( pResize, pos, rData.m_layer );
502 else if( rData.m_actionId == "resizeE" )
504 CtrlResize *pResize = new CtrlResize( getIntf(), *pImage, *pLayout,
505 UString( getIntf(), rData.m_help.c_str() ), NULL,
506 CtrlResize::kResizeE );
507 pLayout->addControl( pResize, pos, rData.m_layer );
509 else if( rData.m_actionId == "resizeSE" )
511 CtrlResize *pResize = new CtrlResize( getIntf(), *pImage, *pLayout,
512 UString( getIntf(), rData.m_help.c_str() ), NULL,
513 CtrlResize::kResizeSE );
514 pLayout->addControl( pResize, pos, rData.m_layer );
518 pLayout->addControl( pImage, pos, rData.m_layer );
521 m_pTheme->m_controls[rData.m_id] = CtrlGenericPtr( pImage );
525 void Builder::addText( const BuilderData::Text &rData )
527 GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
528 if( pLayout == NULL )
530 msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
534 GenericFont *pFont = getFont( rData.m_fontId );
537 msg_Err( getIntf(), "Unknown font id: %s", rData.m_fontId.c_str() );
541 // Convert the scrolling mode
542 CtrlText::Scrolling_t scrolling;
543 if( rData.m_scrolling == "auto" )
544 scrolling = CtrlText::kAutomatic;
545 else if( rData.m_scrolling == "manual" )
546 scrolling = CtrlText::kManual;
547 else if( rData.m_scrolling == "none" )
548 scrolling = CtrlText::kNone;
551 msg_Err( getIntf(), "Invalid scrolling mode: %s",
552 rData.m_scrolling.c_str() );
556 // Convert the alignment
557 CtrlText::Align_t alignment;
558 if( rData.m_alignment == "left" )
559 alignment = CtrlText::kLeft;
560 else if( rData.m_alignment == "center" || rData.m_alignment == "centre" )
561 alignment = CtrlText::kCenter;
562 else if( rData.m_alignment == "right" )
563 alignment = CtrlText::kRight;
566 msg_Err( getIntf(), "Invalid alignment: %s",
567 rData.m_alignment.c_str() );
571 // Create a text variable
572 VarText *pVar = new VarText( getIntf() );
573 m_pTheme->m_vars.push_back( VariablePtr( pVar ) );
575 // Get the visibility variable
576 // XXX check when it is null
577 Interpreter *pInterpreter = Interpreter::instance( getIntf() );
578 VarBool *pVisible = pInterpreter->getVarBool( rData.m_visible, m_pTheme );
580 CtrlText *pText = new CtrlText( getIntf(), *pVar, *pFont,
581 UString( getIntf(), rData.m_help.c_str() ), rData.m_color, pVisible,
582 scrolling, alignment );
584 int height = pFont->getSize();
586 // Compute the position of the control
587 const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
588 rData.m_xPos, rData.m_yPos,
589 rData.m_width, height,
592 pLayout->addControl( pText, pos, rData.m_layer );
594 // Set the text of the control
595 UString msg( getIntf(), rData.m_text.c_str() );
598 m_pTheme->m_controls[rData.m_id] = CtrlGenericPtr( pText );
602 void Builder::addRadialSlider( const BuilderData::RadialSlider &rData )
604 // Get the bitmaps of the slider
605 GenericBitmap *pSeq = NULL;
606 GET_BMP( pSeq, rData.m_sequence );
608 GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
609 if( pLayout == NULL )
611 msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
615 // Get the variable associated to the slider
616 Interpreter *pInterpreter = Interpreter::instance( getIntf() );
617 VarPercent *pVar = pInterpreter->getVarPercent( rData.m_value, m_pTheme );
620 msg_Err( getIntf(), "Unknown slider value: %s", rData.m_value.c_str() );
624 // Get the visibility variable
625 // XXX check when it is null
626 VarBool *pVisible = pInterpreter->getVarBool( rData.m_visible, m_pTheme );
628 // Create the control
629 CtrlRadialSlider *pRadial =
630 new CtrlRadialSlider( getIntf(), *pSeq, rData.m_nbImages, *pVar,
631 rData.m_minAngle, rData.m_maxAngle,
632 UString( getIntf(), rData.m_help.c_str() ),
635 // XXX: resizing is not supported
636 // Compute the position of the control
638 makePosition( rData.m_leftTop, rData.m_rightBottom, rData.m_xPos,
639 rData.m_yPos, pSeq->getWidth(),
640 pSeq->getHeight() / rData.m_nbImages, *pLayout );
642 pLayout->addControl( pRadial, pos, rData.m_layer );
644 m_pTheme->m_controls[rData.m_id] = CtrlGenericPtr( pRadial );
648 void Builder::addSlider( const BuilderData::Slider &rData )
650 // Add the background first, so that we will still have something almost
651 // functional if the cursor cannot be created properly (this happens for
652 // some winamp2 skins, where the images of the cursor are not always
655 // Get the bitmaps of the background
656 GenericBitmap *pBgImage = NULL;
657 if( rData.m_imageId != "none" )
659 GET_BMP( pBgImage, rData.m_imageId );
662 GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
663 if( pLayout == NULL )
665 msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
669 Bezier *pCurve = getPoints( rData.m_points.c_str() );
672 msg_Err( getIntf(), "Invalid format in tag points=\"%s\"",
673 rData.m_points.c_str() );
676 m_pTheme->m_curves.push_back( BezierPtr( pCurve ) );
678 // Get the visibility variable
679 // XXX check when it is null
680 Interpreter *pInterpreter = Interpreter::instance( getIntf() );
681 VarBool *pVisible = pInterpreter->getVarBool( rData.m_visible, m_pTheme );
683 // Get the variable associated to the slider
684 VarPercent *pVar = pInterpreter->getVarPercent( rData.m_value, m_pTheme );
687 msg_Err( getIntf(), "Unknown slider value: %s", rData.m_value.c_str() );
691 // Create the background control
692 CtrlSliderBg *pBackground = new CtrlSliderBg( getIntf(),
693 *pCurve, *pVar, rData.m_thickness, pBgImage, rData.m_nbHoriz,
694 rData.m_nbVert, rData.m_padHoriz, rData.m_padVert,
695 pVisible, UString( getIntf(), rData.m_help.c_str() ) );
697 // Compute the position of the control
698 const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
699 rData.m_xPos, rData.m_yPos,
700 pCurve->getWidth(), pCurve->getHeight(),
703 pLayout->addControl( pBackground, pos, rData.m_layer );
705 m_pTheme->m_controls[rData.m_id + "_bg"] = CtrlGenericPtr( pBackground );
707 // Get the bitmaps of the cursor
708 GenericBitmap *pBmpUp = NULL;
709 GET_BMP( pBmpUp, rData.m_upId );
711 GenericBitmap *pBmpDown = pBmpUp;
712 GET_BMP( pBmpDown, rData.m_downId );
714 GenericBitmap *pBmpOver = pBmpUp;
715 GET_BMP( pBmpOver, rData.m_overId );
717 // Create the cursor control
718 CtrlSliderCursor *pCursor = new CtrlSliderCursor( getIntf(), *pBmpUp,
719 *pBmpOver, *pBmpDown, *pCurve, *pVar, pVisible,
720 UString( getIntf(), rData.m_tooltip.c_str() ),
721 UString( getIntf(), rData.m_help.c_str() ) );
723 pLayout->addControl( pCursor, pos, rData.m_layer );
725 m_pTheme->m_controls[rData.m_id] = CtrlGenericPtr( pCursor );
727 // Associate the cursor to the background
728 pBackground->associateCursor( *pCursor );
732 void Builder::addList( const BuilderData::List &rData )
734 // Get the background bitmap, if any
735 GenericBitmap *pBgBmp = NULL;
736 GET_BMP( pBgBmp, rData.m_bgImageId );
738 GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
739 if( pLayout == NULL )
741 msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
745 GenericFont *pFont = getFont( rData.m_fontId );
748 msg_Err( getIntf(), "Unknown font id: %s", rData.m_fontId.c_str() );
752 // Get the list variable
753 Interpreter *pInterpreter = Interpreter::instance( getIntf() );
754 VarList *pVar = pInterpreter->getVarList( rData.m_var, m_pTheme );
757 msg_Err( getIntf(), "No such list variable: %s", rData.m_var.c_str() );
761 // Get the visibility variable
762 // XXX check when it is null
763 VarBool *pVisible = pInterpreter->getVarBool( rData.m_visible, m_pTheme );
765 // Create the list control
766 CtrlList *pList = new CtrlList( getIntf(), *pVar, *pFont, pBgBmp,
767 rData.m_fgColor, rData.m_playColor, rData.m_bgColor1,
768 rData.m_bgColor2, rData.m_selColor,
769 UString( getIntf(), rData.m_help.c_str() ), pVisible );
771 // Compute the position of the control
772 const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
773 rData.m_xPos, rData.m_yPos,
774 rData.m_width, rData.m_height,
777 pLayout->addControl( pList, pos, rData.m_layer );
779 m_pTheme->m_controls[rData.m_id] = CtrlGenericPtr( pList );
782 void Builder::addTree( const BuilderData::Tree &rData )
784 // Get the bitmaps, if any
785 GenericBitmap *pBgBmp = NULL;
786 GenericBitmap *pItemBmp = NULL;
787 GenericBitmap *pOpenBmp = NULL;
788 GenericBitmap *pClosedBmp = NULL;
789 GET_BMP( pBgBmp, rData.m_bgImageId );
790 GET_BMP( pItemBmp, rData.m_itemImageId );
791 GET_BMP( pOpenBmp, rData.m_openImageId );
792 GET_BMP( pClosedBmp, rData.m_closedImageId );
794 GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
795 if( pLayout == NULL )
797 msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
801 GenericFont *pFont = getFont( rData.m_fontId );
804 msg_Err( getIntf(), "Unknown font id: %s", rData.m_fontId.c_str() );
808 // Get the list variable
809 Interpreter *pInterpreter = Interpreter::instance( getIntf() );
810 VarTree *pVar = pInterpreter->getVarTree( rData.m_var, m_pTheme );
813 msg_Err( getIntf(), "No such list variable: %s", rData.m_var.c_str() );
817 // Get the visibility variable
818 // XXX check when it is null
819 VarBool *pVisible = pInterpreter->getVarBool( rData.m_visible, m_pTheme );
821 // Create the list control
822 CtrlTree *pTree = new CtrlTree( getIntf(), *pVar, *pFont, pBgBmp,
823 pItemBmp, pOpenBmp, pClosedBmp,
824 rData.m_fgColor, rData.m_playColor, rData.m_bgColor1,
825 rData.m_bgColor2, rData.m_selColor,
826 UString( getIntf(), rData.m_help.c_str() ), pVisible );
828 // Compute the position of the control
829 const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
830 rData.m_xPos, rData.m_yPos,
831 rData.m_width, rData.m_height,
834 pLayout->addControl( pTree, pos, rData.m_layer );
836 m_pTheme->m_controls[rData.m_id] = CtrlGenericPtr( pTree );
839 void Builder::addVideo( const BuilderData::Video &rData )
841 GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
842 if( pLayout == NULL )
844 msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
848 // Get the visibility variable
849 // XXX check when it is null
850 Interpreter *pInterpreter = Interpreter::instance( getIntf() );
851 VarBool *pVisible = pInterpreter->getVarBool( rData.m_visible, m_pTheme );
853 CtrlVideo *pVideo = new CtrlVideo( getIntf(), *pLayout,
854 rData.m_autoResize, UString( getIntf(), rData.m_help.c_str() ),
857 // Compute the position of the control
858 const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
859 rData.m_xPos, rData.m_yPos,
860 rData.m_width, rData.m_height,
863 pLayout->addControl( pVideo, pos, rData.m_layer );
865 m_pTheme->m_controls[rData.m_id] = CtrlGenericPtr( pVideo );
869 const Position Builder::makePosition( const string &rLeftTop,
870 const string &rRightBottom,
871 int xPos, int yPos, int width,
872 int height, const Box &rBox ) const
874 int left = 0, top = 0, right = 0, bottom = 0;
875 Position::Ref_t refLeftTop = Position::kLeftTop;
876 Position::Ref_t refRightBottom = Position::kLeftTop;
878 int boxWidth = rBox.getWidth();
879 int boxHeight = rBox.getHeight();
881 // Position of the left top corner
882 if( rLeftTop == "lefttop" )
886 refLeftTop = Position::kLeftTop;
888 else if( rLeftTop == "righttop" )
890 left = xPos - boxWidth + 1;
892 refLeftTop = Position::kRightTop;
894 else if( rLeftTop == "leftbottom" )
897 top = yPos - boxHeight + 1;
898 refLeftTop = Position::kLeftBottom;
900 else if( rLeftTop == "rightbottom" )
902 left = xPos - boxWidth + 1;
903 top = yPos - boxHeight + 1;
904 refLeftTop = Position::kRightBottom;
907 // Position of the right bottom corner
908 if( rRightBottom == "lefttop" )
910 right = xPos + width - 1;
911 bottom = yPos + height - 1;
912 refRightBottom = Position::kLeftTop;
914 else if( rRightBottom == "righttop" )
916 right = xPos + width - boxWidth;
917 bottom = yPos + height - 1;
918 refRightBottom = Position::kRightTop;
920 else if( rRightBottom == "leftbottom" )
922 right = xPos + width - 1;
923 bottom = yPos + height - boxHeight;
924 refRightBottom = Position::kLeftBottom;
926 else if( rRightBottom == "rightbottom" )
928 right = xPos + width - boxWidth;
929 bottom = yPos + height - boxHeight;
930 refRightBottom = Position::kRightBottom;
933 return Position( left, top, right, bottom, rBox, refLeftTop,
938 GenericFont *Builder::getFont( const string &fontId )
940 GenericFont *pFont = m_pTheme->getFontById(fontId);
941 if( !pFont && fontId == "defaultfont" )
943 // Get the resource path and try to load the default font
944 OSFactory *pOSFactory = OSFactory::instance( getIntf() );
945 const list<string> &resPath = pOSFactory->getResourcePath();
946 const string &sep = pOSFactory->getDirSeparator();
948 list<string>::const_iterator it;
949 for( it = resPath.begin(); it != resPath.end(); it++ )
951 string path = (*it) + sep + "fonts" + sep + "FreeSans.ttf";
952 pFont = new FT2Font( getIntf(), path, 12 );
955 // Font loaded successfully
956 m_pTheme->m_fonts["defaultfont"] = GenericFontPtr( pFont );
967 msg_Err( getIntf(), "Failed to open the default font" );
974 string Builder::getFilePath( const string &rFileName ) const
976 OSFactory *pFactory = OSFactory::instance( getIntf() );
977 return m_path + pFactory->getDirSeparator() + rFileName;
982 Bezier *Builder::getPoints( const char *pTag ) const
984 vector<float> xBez, yBez;
988 if( sscanf( pTag, "(%d,%d)%n", &x, &y, &n ) < 1 )
996 "Slider points cannot have negative coordinates!" );
1000 xBez.push_back( x );
1001 yBez.push_back( y );
1007 if( *(pTag++) != ',' )
1013 // Create the Bezier curve
1014 return new Bezier( getIntf(), xBez, yBez );