1 /***************************************************************************
2  *   Copyright (C) 2009 by Andrey Afletdinov <fheroes2@gmail.com>          *
3  *                                                                         *
4  *   Part of the Free Heroes2 Engine:                                      *
5  *   http://sourceforge.net/projects/fheroes2                              *
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
21  ***************************************************************************/
22 
23 #include "interface_icons.h"
24 #include "agg_image.h"
25 #include "castle_ui.h"
26 #include "game.h"
27 #include "game_interface.h"
28 #include "heroes.h"
29 #include "icn.h"
30 #include "kingdom.h"
31 #include "settings.h"
32 #include "world.h"
33 
34 namespace
35 {
36     enum
37     {
38         ICONS_WIDTH = 46,
39         ICONS_HEIGHT = 22,
40         ICONS_CURSOR_WIDTH = 56,
41         ICONS_CURSOR_HEIGHT = 32
42     };
43 }
44 
IsVisible(void)45 bool Interface::IconsBar::IsVisible( void )
46 {
47     const Settings & conf = Settings::Get();
48     return !conf.ExtGameHideInterface() || conf.ShowIcons();
49 }
50 
GetItemWidth(void)51 u32 Interface::IconsBar::GetItemWidth( void )
52 {
53     return ICONS_WIDTH;
54 }
55 
GetItemHeight(void)56 u32 Interface::IconsBar::GetItemHeight( void )
57 {
58     return ICONS_HEIGHT;
59 }
60 
RedrawCastleIcon(const Castle & castle,int32_t sx,int32_t sy)61 void Interface::RedrawCastleIcon( const Castle & castle, int32_t sx, int32_t sy )
62 {
63     fheroes2::drawCastleIcon( castle, fheroes2::Display::instance(), fheroes2::Point( sx, sy ) );
64 }
65 
RedrawHeroesIcon(const Heroes & hero,s32 sx,s32 sy)66 void Interface::RedrawHeroesIcon( const Heroes & hero, s32 sx, s32 sy )
67 {
68     hero.PortraitRedraw( sx, sy, PORT_SMALL, fheroes2::Display::instance() );
69 }
70 
RedrawBackground(const fheroes2::Point & pos) const71 void Interface::IconsBar::RedrawBackground( const fheroes2::Point & pos ) const
72 {
73     fheroes2::Display & display = fheroes2::Display::instance();
74     const bool isEvilInterface = Settings::Get().ExtGameEvilInterface();
75 
76     const fheroes2::Sprite & icnadv = fheroes2::AGG::GetICN( isEvilInterface ? ICN::ADVBORDE : ICN::ADVBORD, 0 );
77     const fheroes2::Sprite & back = fheroes2::AGG::GetICN( isEvilInterface ? ICN::LOCATORE : ICN::LOCATORS, 1 );
78     fheroes2::Rect srcrt( icnadv.width() - RADARWIDTH - BORDERWIDTH, RADARWIDTH + 2 * BORDERWIDTH, RADARWIDTH / 2, 32 );
79 
80     fheroes2::Point dstpt( pos.x, pos.y );
81     fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height );
82 
83     srcrt.y = srcrt.y + srcrt.height;
84     dstpt.y = dstpt.y + srcrt.height;
85     srcrt.height = 32;
86 
87     if ( 2 < iconsCount ) {
88         for ( uint32_t i = 0; i < iconsCount - 2; ++i ) {
89             fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height );
90             dstpt.y += srcrt.height;
91         }
92     }
93 
94     srcrt.y = srcrt.y + 64;
95     srcrt.height = 32;
96     fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height );
97 
98     for ( u32 ii = 0; ii < iconsCount; ++ii )
99         fheroes2::Blit( back, display, pos.x + 5, pos.y + 5 + ii * ( IconsBar::GetItemHeight() + 10 ) );
100 }
101 
102 /* Interface::CastleIcons */
RedrawItem(const CASTLE & item,s32 ox,s32 oy,bool current)103 void Interface::CastleIcons::RedrawItem( const CASTLE & item, s32 ox, s32 oy, bool current )
104 {
105     if ( item && show ) {
106         RedrawCastleIcon( *item, ox + 5, oy + 5 );
107 
108         if ( current )
109             fheroes2::Blit( marker, fheroes2::Display::instance(), ox, oy );
110     }
111 }
112 
RedrawBackground(const fheroes2::Point & pos)113 void Interface::CastleIcons::RedrawBackground( const fheroes2::Point & pos )
114 {
115     IconsBar::RedrawBackground( pos );
116 }
117 
ActionCurrentUp(void)118 void Interface::CastleIcons::ActionCurrentUp( void )
119 {
120     Interface::Basic::Get().SetFocus( GetCurrent() );
121 }
122 
ActionCurrentDn(void)123 void Interface::CastleIcons::ActionCurrentDn( void )
124 {
125     Interface::Basic::Get().SetFocus( GetCurrent() );
126 }
127 
ActionListDoubleClick(CASTLE & item)128 void Interface::CastleIcons::ActionListDoubleClick( CASTLE & item )
129 {
130     if ( item ) {
131         Game::OpenCastleDialog( *item );
132     }
133 }
134 
ActionListSingleClick(CASTLE & item)135 void Interface::CastleIcons::ActionListSingleClick( CASTLE & item )
136 {
137     if ( item ) {
138         Interface::Basic & I = Interface::Basic::Get();
139 
140         I.SetFocus( item );
141         I.RedrawFocus();
142     }
143 }
144 
ActionListPressRight(CASTLE & castle)145 void Interface::CastleIcons::ActionListPressRight( CASTLE & castle )
146 {
147     if ( castle ) {
148         const fheroes2::Point p( _topLeftCorner.x - 1, _topLeftCorner.y );
149         Dialog::QuickInfo( *castle, fheroes2::Rect(), p );
150     }
151 }
152 
SetShow(bool f)153 void Interface::CastleIcons::SetShow( bool f )
154 {
155     IconsBar::SetShow( f );
156 
157     if ( IconsBar::IsVisible() ) {
158         if ( f )
159             GetScrollbar().show();
160         else
161             GetScrollbar().hide();
162     }
163 }
164 
SetPos(s32 px,s32 py)165 void Interface::CastleIcons::SetPos( s32 px, s32 py )
166 {
167     const int icnscroll = Settings::Get().ExtGameEvilInterface() ? ICN::SCROLLE : ICN::SCROLL;
168 
169     _topLeftCorner = fheroes2::Point( px, py );
170     SetTopLeft( _topLeftCorner );
171     SetScrollBar( fheroes2::AGG::GetICN( icnscroll, 4 ), fheroes2::Rect( px + ICONS_CURSOR_WIDTH + 3, py + 19, 10, ICONS_CURSOR_HEIGHT * iconsCount - 38 ) );
172     SetScrollButtonUp( icnscroll, 0, 1, fheroes2::Point( px + ICONS_CURSOR_WIDTH + 1, py + 1 ) );
173     SetScrollButtonDn( icnscroll, 2, 3, fheroes2::Point( px + ICONS_CURSOR_WIDTH + 1, py + iconsCount * ICONS_CURSOR_HEIGHT - 15 ) );
174     SetAreaMaxItems( iconsCount );
175     SetAreaItems( fheroes2::Rect( px, py, ICONS_CURSOR_WIDTH, iconsCount * ICONS_CURSOR_HEIGHT ) );
176     DisableHotkeys( true );
177 
178     SetListContent( world.GetKingdom( Settings::Get().CurrentColor() ).GetCastles() );
179     Reset();
180 }
181 
182 /* Interface::HeroesIcons */
RedrawItem(const HEROES & item,s32 ox,s32 oy,bool current)183 void Interface::HeroesIcons::RedrawItem( const HEROES & item, s32 ox, s32 oy, bool current )
184 {
185     if ( item && show ) {
186         RedrawHeroesIcon( *item, ox + 5, oy + 5 );
187 
188         if ( current )
189             fheroes2::Blit( marker, fheroes2::Display::instance(), ox, oy );
190     }
191 }
192 
RedrawBackground(const fheroes2::Point & pos)193 void Interface::HeroesIcons::RedrawBackground( const fheroes2::Point & pos )
194 {
195     IconsBar::RedrawBackground( pos );
196 }
197 
ActionCurrentUp(void)198 void Interface::HeroesIcons::ActionCurrentUp( void )
199 {
200     Interface::Basic::Get().SetFocus( GetCurrent() );
201 }
202 
ActionCurrentDn(void)203 void Interface::HeroesIcons::ActionCurrentDn( void )
204 {
205     Interface::Basic::Get().SetFocus( GetCurrent() );
206 }
207 
ActionListDoubleClick(HEROES & item)208 void Interface::HeroesIcons::ActionListDoubleClick( HEROES & item )
209 {
210     if ( item ) {
211         if ( item->Modes( Heroes::GUARDIAN ) ) {
212             Castle * castle = world.getCastle( item->GetCenter() );
213             if ( castle )
214                 Game::OpenCastleDialog( *castle );
215         }
216         else
217             Game::OpenHeroesDialog( *item, false, true );
218     }
219 }
220 
ActionListSingleClick(HEROES & item)221 void Interface::HeroesIcons::ActionListSingleClick( HEROES & item )
222 {
223     if ( item ) {
224         Interface::Basic & I = Interface::Basic::Get();
225 
226         I.SetFocus( item );
227         I.CalculateHeroPath( item, -1 );
228         I.RedrawFocus();
229     }
230 }
231 
ActionListPressRight(HEROES & item)232 void Interface::HeroesIcons::ActionListPressRight( HEROES & item )
233 {
234     if ( item ) {
235         const fheroes2::Point p( _topLeftCorner.x - 1, _topLeftCorner.y );
236         Dialog::QuickInfo( *item, fheroes2::Rect(), p );
237     }
238 }
239 
SetShow(bool f)240 void Interface::HeroesIcons::SetShow( bool f )
241 {
242     IconsBar::SetShow( f );
243 
244     if ( IconsBar::IsVisible() ) {
245         if ( f )
246             GetScrollbar().show();
247         else
248             GetScrollbar().hide();
249     }
250 }
251 
SetPos(s32 px,s32 py)252 void Interface::HeroesIcons::SetPos( s32 px, s32 py )
253 {
254     const int icnscroll = Settings::Get().ExtGameEvilInterface() ? ICN::SCROLLE : ICN::SCROLL;
255 
256     _topLeftCorner = fheroes2::Point( px, py );
257     SetTopLeft( _topLeftCorner );
258     SetScrollBar( fheroes2::AGG::GetICN( icnscroll, 4 ), fheroes2::Rect( px + ICONS_CURSOR_WIDTH + 3, py + 19, 10, ICONS_CURSOR_HEIGHT * iconsCount - 38 ) );
259     SetScrollButtonUp( icnscroll, 0, 1, fheroes2::Point( px + ICONS_CURSOR_WIDTH + 1, py + 1 ) );
260     SetScrollButtonDn( icnscroll, 2, 3, fheroes2::Point( px + ICONS_CURSOR_WIDTH + 1, py + iconsCount * ICONS_CURSOR_HEIGHT - 15 ) );
261     SetAreaMaxItems( iconsCount );
262     SetAreaItems( fheroes2::Rect( px, py, ICONS_CURSOR_WIDTH, iconsCount * ICONS_CURSOR_HEIGHT ) );
263     DisableHotkeys( true );
264 
265     SetListContent( world.GetKingdom( Settings::Get().CurrentColor() ).GetHeroes() );
266     Reset();
267 }
268 
269 /* Interface::IconsPanel */
IconsPanel(Basic & basic)270 Interface::IconsPanel::IconsPanel( Basic & basic )
271     : BorderWindow( fheroes2::Rect( 0, 0, 144, 128 ) )
272     , interface( basic )
273     , castleIcons( 4, sfMarker )
274     , heroesIcons( 4, sfMarker )
275 {
276     sfMarker.resize( ICONS_CURSOR_WIDTH, ICONS_CURSOR_HEIGHT );
277     sfMarker.reset();
278     fheroes2::DrawBorder( sfMarker, fheroes2::GetColorId( 0xA0, 0xE0, 0xE0 ) );
279 }
280 
SavePosition(void)281 void Interface::IconsPanel::SavePosition( void )
282 {
283     Settings::Get().SetPosIcons( GetRect().getPosition() );
284 }
285 
SetRedraw(icons_t type) const286 void Interface::IconsPanel::SetRedraw( icons_t type ) const
287 {
288     // is visible
289     if ( IconsBar::IsVisible() ) {
290         switch ( type ) {
291         case ICON_HEROES:
292             interface.SetRedraw( REDRAW_HEROES );
293             break;
294         case ICON_CASTLES:
295             interface.SetRedraw( REDRAW_CASTLES );
296             break;
297         default:
298             break;
299         }
300 
301         interface.SetRedraw( REDRAW_ICONS );
302     }
303 }
304 
SetRedraw(void) const305 void Interface::IconsPanel::SetRedraw( void ) const
306 {
307     SetRedraw( ICON_ANY );
308 }
309 
SetPos(s32 ox,s32 oy)310 void Interface::IconsPanel::SetPos( s32 ox, s32 oy )
311 {
312     u32 iconsCount = 0;
313 
314     if ( Settings::Get().ExtGameHideInterface() ) {
315         iconsCount = 2;
316     }
317     else {
318         const u32 count_h = ( fheroes2::Display::instance().height() - fheroes2::Display::DEFAULT_HEIGHT ) / TILEWIDTH;
319         iconsCount = count_h > 3 ? 8 : ( count_h < 3 ? 4 : 7 );
320     }
321 
322     BorderWindow::SetPosition( ox, oy, 144, iconsCount * ICONS_CURSOR_HEIGHT );
323 
324     const fheroes2::Rect & rect = GetArea();
325 
326     heroesIcons.SetIconsCount( iconsCount );
327     castleIcons.SetIconsCount( iconsCount );
328 
329     heroesIcons.SetPos( rect.x, rect.y );
330     castleIcons.SetPos( rect.x + 72, rect.y );
331 }
332 
Redraw(void)333 void Interface::IconsPanel::Redraw( void )
334 {
335     // is visible
336     if ( IconsBar::IsVisible() ) {
337         // redraw border
338         if ( Settings::Get().ExtGameHideInterface() )
339             BorderWindow::Redraw();
340 
341         heroesIcons.Redraw();
342         castleIcons.Redraw();
343     }
344 }
345 
QueueEventProcessing(void)346 void Interface::IconsPanel::QueueEventProcessing( void )
347 {
348     if ( Settings::Get().ShowIcons() &&
349          // move border window
350          BorderWindow::QueueEventProcessing() ) {
351         interface.RedrawFocus();
352         SetRedraw();
353     }
354     else if ( heroesIcons.QueueEventProcessing() ) {
355         if ( heroesIcons.isSelected() )
356             castleIcons.Unselect();
357 
358         SetRedraw();
359     }
360     else if ( castleIcons.QueueEventProcessing() ) {
361         if ( castleIcons.isSelected() )
362             heroesIcons.Unselect();
363 
364         SetRedraw();
365     }
366 }
367 
Select(Heroes * const hr)368 void Interface::IconsPanel::Select( Heroes * const hr )
369 {
370     castleIcons.Unselect();
371     heroesIcons.SetCurrent( hr );
372 }
373 
Select(Castle * const cs)374 void Interface::IconsPanel::Select( Castle * const cs )
375 {
376     heroesIcons.Unselect();
377     castleIcons.SetCurrent( cs );
378 }
379 
ResetIcons(icons_t type)380 void Interface::IconsPanel::ResetIcons( icons_t type )
381 {
382     Kingdom & kingdom = world.GetKingdom( Settings::Get().CurrentColor() );
383 
384     if ( !kingdom.isControlAI() ) {
385         if ( type & ICON_HEROES ) {
386             heroesIcons.SetListContent( kingdom.GetHeroes() );
387             heroesIcons.Reset();
388         }
389 
390         if ( type & ICON_CASTLES ) {
391             castleIcons.SetListContent( kingdom.GetCastles() );
392             castleIcons.Reset();
393         }
394     }
395 }
396 
HideIcons(icons_t type)397 void Interface::IconsPanel::HideIcons( icons_t type )
398 {
399     if ( type & ICON_HEROES )
400         heroesIcons.SetShow( false );
401     if ( type & ICON_CASTLES )
402         castleIcons.SetShow( false );
403 }
404 
ShowIcons(icons_t type)405 void Interface::IconsPanel::ShowIcons( icons_t type )
406 {
407     if ( type & ICON_HEROES )
408         heroesIcons.SetShow( true );
409     if ( type & ICON_CASTLES )
410         castleIcons.SetShow( true );
411 }
412 
SetCurrentVisible(void)413 void Interface::IconsPanel::SetCurrentVisible( void )
414 {
415     if ( heroesIcons.isSelected() ) {
416         heroesIcons.SetCurrentVisible();
417         heroesIcons.Redraw();
418     }
419     else if ( castleIcons.isSelected() ) {
420         castleIcons.SetCurrentVisible();
421         castleIcons.Redraw();
422     }
423 }
424 
RedrawIcons(icons_t type)425 void Interface::IconsPanel::RedrawIcons( icons_t type )
426 {
427     if ( type & ICON_HEROES )
428         heroesIcons.Redraw();
429     if ( type & ICON_CASTLES )
430         castleIcons.Redraw();
431 }
432 
IsSelected(icons_t type) const433 bool Interface::IconsPanel::IsSelected( icons_t type ) const
434 {
435     if ( type & ICON_HEROES )
436         return heroesIcons.isSelected();
437     else if ( type & ICON_CASTLES )
438         return castleIcons.isSelected();
439 
440     return false;
441 }
442