]> git.sesse.net Git - vlc/blob - modules/gui/skins2/controls/ctrl_image.cpp
skins2: implement art display in image controls
[vlc] / modules / gui / skins2 / controls / ctrl_image.cpp
1 /*****************************************************************************
2  * ctrl_image.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8  *          Olivier Teulière <ipkiss@via.ecp.fr>
9  *
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.
14  *
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.
19  *
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #include "ctrl_image.hpp"
26 #include "../commands/cmd_dialogs.hpp"
27 #include "../events/evt_generic.hpp"
28 #include "../src/os_factory.hpp"
29 #include "../src/os_graphics.hpp"
30 #include "../src/vlcproc.hpp"
31 #include "../src/scaled_bitmap.hpp"
32 #include "../src/art_bitmap.hpp"
33 #include "../utils/position.hpp"
34
35
36 CtrlImage::CtrlImage( intf_thread_t *pIntf, GenericBitmap &rBitmap,
37                       CmdGeneric &rCommand, resize_t resizeMethod,
38                       const UString &rHelp, VarBool *pVisible, bool art ):
39     CtrlFlat( pIntf, rHelp, pVisible ),
40     m_pBitmap( &rBitmap ), m_pOriginalBitmap( &rBitmap ),
41     m_rCommand( rCommand ), m_resizeMethod( resizeMethod ), m_art( art )
42 {
43     // Create an initial unscaled image in the buffer
44     m_pImage = OSFactory::instance( pIntf )->createOSGraphics(
45                                     rBitmap.getWidth(), rBitmap.getHeight() );
46     m_pImage->drawBitmap( *m_pBitmap );
47
48     // Observe the variable
49     if( m_art )
50     {
51         VlcProc *pVlcProc = VlcProc::instance( getIntf() );
52         pVlcProc->getStreamArtVar().addObserver( this );
53
54         ArtBitmap::initArtBitmap( getIntf() );
55     }
56
57 }
58
59
60 CtrlImage::~CtrlImage()
61 {
62     delete m_pImage;
63
64     if( m_art )
65     {
66         VlcProc *pVlcProc = VlcProc::instance( getIntf() );
67         pVlcProc->getStreamArtVar().delObserver( this );
68
69         ArtBitmap::freeArtBitmap( );
70     }
71 }
72
73
74 void CtrlImage::handleEvent( EvtGeneric &rEvent )
75 {
76     // No FSM for this simple transition
77     if( rEvent.getAsString() == "mouse:right:up:none" )
78     {
79         CmdDlgShowPopupMenu( getIntf() ).execute();
80     }
81     else if( rEvent.getAsString() == "mouse:left:up:none" )
82     {
83         CmdDlgHidePopupMenu( getIntf() ).execute();
84         CmdDlgHideVideoPopupMenu( getIntf() ).execute();
85         CmdDlgHideAudioPopupMenu( getIntf() ).execute();
86         CmdDlgHideMiscPopupMenu( getIntf() ).execute();
87     }
88     else if( rEvent.getAsString() == "mouse:left:dblclick:none" )
89     {
90         m_rCommand.execute();
91     }
92 }
93
94
95 bool CtrlImage::mouseOver( int x, int y ) const
96 {
97     if( m_resizeMethod == kMosaic &&
98         x >= 0 && x < getPosition()->getWidth() &&
99         y >= 0 && y < getPosition()->getHeight() )
100     {
101         // In mosaic mode, convert the coordinates to make them fit to the
102         // size of the original image
103         x %= m_pImage->getWidth();
104         y %= m_pImage->getHeight();
105     }
106     return m_pImage->hit( x, y );
107 }
108
109
110 void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
111 {
112     const Position *pPos = getPosition();
113     if( pPos )
114     {
115         int width = pPos->getWidth();
116         int height = pPos->getHeight();
117
118         if( m_resizeMethod == kScale )
119         {
120             // Use scaling method
121             if( width > 0 && height > 0 )
122             {
123                 if( width != m_pImage->getWidth() ||
124                     height != m_pImage->getHeight() )
125                 {
126                     OSFactory *pOsFactory = OSFactory::instance( getIntf() );
127                     // Rescale the image with the actual size of the control
128                     ScaledBitmap bmp( getIntf(), *m_pBitmap, width, height );
129                     delete m_pImage;
130                     m_pImage = pOsFactory->createOSGraphics( width, height );
131                     m_pImage->drawBitmap( bmp, 0, 0 );
132                 }
133                 rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
134             }
135         }
136         else if( m_resizeMethod == kMosaic )
137         {
138             // Use mosaic method
139             while( width > 0 )
140             {
141                 int curWidth = __MIN( width, m_pImage->getWidth() );
142                 height = pPos->getHeight();
143                 int curYDest = yDest;
144                 while( height > 0 )
145                 {
146                     int curHeight = __MIN( height, m_pImage->getHeight() );
147                     rImage.drawGraphics( *m_pImage, 0, 0, xDest, curYDest,
148                                          curWidth, curHeight );
149                     curYDest += curHeight;
150                     height -= m_pImage->getHeight();
151                 }
152                 xDest += curWidth;
153                 width -= m_pImage->getWidth();
154             }
155         }
156         else if( m_resizeMethod == kScaleAndRatioPreserved )
157         {
158             int width = pPos->getWidth();
159             int height = pPos->getHeight();
160
161             int w = m_pBitmap->getWidth();
162             int h = m_pBitmap->getHeight();
163
164             int scaled_height = width * h / w;
165             int scaled_width  = height * w / h;
166
167             int x, y;
168
169             if( scaled_height > height )
170             {
171                 width = scaled_width;
172                 x = ( pPos->getWidth() - width ) / 2;
173                 y = 0;
174             }
175             else
176             {
177                 height = scaled_height;
178                 x =  0;
179                 y = ( pPos->getHeight() - height ) / 2;
180             }
181
182             OSFactory *pOsFactory = OSFactory::instance( getIntf() );
183             // Rescale the image with the actual size of the control
184             ScaledBitmap bmp( getIntf(), *m_pBitmap, width, height );
185             delete m_pImage;
186             m_pImage = pOsFactory->createOSGraphics( width, height );
187             m_pImage->drawBitmap( bmp, 0, 0 );
188
189             rImage.drawGraphics( *m_pImage, 0, 0, xDest + x, yDest + y );
190         }
191     }
192 }
193
194 void CtrlImage::onUpdate( Subject<VarString> &rVariable, void* arg )
195 {
196     VlcProc *pVlcProc = VlcProc::instance( getIntf() );
197
198     if( &rVariable == &pVlcProc->getStreamArtVar() )
199     {
200         string str = ((VarString&)rVariable).get();
201         GenericBitmap* pArt = (GenericBitmap*) ArtBitmap::getArtBitmap( str );
202
203         m_pBitmap = pArt ? pArt : m_pOriginalBitmap;
204
205         msg_Dbg( getIntf(), "art file %s to be displayed (wxh = %ix%i)",
206                             str.c_str(),
207                             m_pBitmap->getWidth(),
208                             m_pBitmap->getHeight() );
209
210         delete m_pImage;
211         m_pImage = OSFactory::instance( getIntf() )->createOSGraphics(
212                                         m_pBitmap->getWidth(),
213                                         m_pBitmap->getHeight() );
214         m_pImage->drawBitmap( *m_pBitmap );
215
216         notifyLayout();
217     }
218 }
219
220