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 "agg_image.h"
24 #include "dialog.h"
25 #include "icn.h"
26 #include "screen.h"
27 #include "settings.h"
28 
29 #include <algorithm>
30 
31 namespace
32 {
33     const int32_t windowWidth = 288; // this is measured value
34     const int32_t buttonHeight = 40;
35     const int32_t activeAreaHeight = 35;
36 
topHeight(const bool isEvilInterface)37     int32_t topHeight( const bool isEvilInterface )
38     {
39         const fheroes2::Sprite & image = fheroes2::AGG::GetICN( isEvilInterface ? ICN::BUYBUILE : ICN::BUYBUILD, 0 );
40         return image.height();
41     }
42 
bottomHeight(const bool isEvilInterface)43     int32_t bottomHeight( const bool isEvilInterface )
44     {
45         const fheroes2::Sprite & image = fheroes2::AGG::GetICN( isEvilInterface ? ICN::BUYBUILE : ICN::BUYBUILD, 2 );
46         return image.height();
47     }
48 
leftWidth(const bool isEvilInterface)49     int32_t leftWidth( const bool isEvilInterface )
50     {
51         const int icnId = isEvilInterface ? ICN::BUYBUILE : ICN::BUYBUILD;
52 
53         const fheroes2::Sprite & image3 = fheroes2::AGG::GetICN( icnId, 3 );
54         const fheroes2::Sprite & image4 = fheroes2::AGG::GetICN( icnId, 4 );
55         const fheroes2::Sprite & image5 = fheroes2::AGG::GetICN( icnId, 5 );
56 
57         int32_t widthLeft = image3.width();
58         widthLeft = std::max( widthLeft, image4.width() );
59         widthLeft = std::max( widthLeft, image5.width() );
60 
61         return widthLeft;
62     }
63 
rightWidth(const bool isEvilInterface)64     int32_t rightWidth( const bool isEvilInterface )
65     {
66         const int icnId = isEvilInterface ? ICN::BUYBUILE : ICN::BUYBUILD;
67 
68         const fheroes2::Sprite & image0 = fheroes2::AGG::GetICN( icnId, 0 );
69         const fheroes2::Sprite & image1 = fheroes2::AGG::GetICN( icnId, 1 );
70         const fheroes2::Sprite & image2 = fheroes2::AGG::GetICN( icnId, 2 );
71 
72         int32_t widthRight = image0.width();
73         widthRight = std::max( widthRight, image1.width() );
74         widthRight = std::max( widthRight, image2.width() );
75 
76         return widthRight;
77     }
78 
overallWidth(const bool isEvilInterface)79     int32_t overallWidth( const bool isEvilInterface )
80     {
81         return leftWidth( isEvilInterface ) + rightWidth( isEvilInterface );
82     }
83 
leftOffset(const bool isEvilInterface)84     int32_t leftOffset( const bool isEvilInterface )
85     {
86         return leftWidth( isEvilInterface ) - windowWidth / 2;
87     }
88 }
89 
NonFixedFrameBox(int height,int startYPos,bool showButtons)90 Dialog::NonFixedFrameBox::NonFixedFrameBox( int height, int startYPos, bool showButtons )
91     : _middleFragmentCount( 0 )
92     , _middleFragmentHeight( 0 )
93 {
94     if ( showButtons )
95         height += buttonHeight;
96 
97     const bool evil = Settings::Get().ExtGameEvilInterface();
98     _middleFragmentCount = ( height <= 2 * activeAreaHeight ? 0 : 1 + ( height - 2 * activeAreaHeight ) / activeAreaHeight );
99     _middleFragmentHeight = height <= 2 * activeAreaHeight ? 0 : height - 2 * activeAreaHeight;
100     const int32_t height_top_bottom = topHeight( evil ) + bottomHeight( evil );
101 
102     area.width = BOXAREA_WIDTH;
103     area.height = activeAreaHeight + activeAreaHeight + _middleFragmentHeight;
104 
105     fheroes2::Display & display = fheroes2::Display::instance();
106     const int32_t leftSideOffset = leftOffset( evil );
107 
108     _position.x = ( display.width() - windowWidth ) / 2 - leftSideOffset;
109     _position.y = startYPos;
110 
111     if ( startYPos < 0 ) {
112         _position.y = ( ( display.height() - _middleFragmentHeight ) / 2 ) - topHeight( evil );
113     }
114 
115     _restorer.reset( new fheroes2::ImageRestorer( display, _position.x, _position.y, overallWidth( evil ), height_top_bottom + _middleFragmentHeight ) );
116 
117     area.x = _position.x + ( windowWidth - BOXAREA_WIDTH ) / 2 + leftSideOffset;
118     area.y = _position.y + ( topHeight( evil ) - activeAreaHeight );
119 
120     redraw();
121 }
122 
redraw()123 void Dialog::NonFixedFrameBox::redraw()
124 {
125     const bool isEvilInterface = Settings::Get().ExtGameEvilInterface();
126     const int buybuild = isEvilInterface ? ICN::BUYBUILE : ICN::BUYBUILD;
127 
128     const int32_t overallLeftWidth = leftWidth( isEvilInterface );
129 
130     // right-top
131     const fheroes2::Sprite & part0 = fheroes2::AGG::GetICN( buybuild, 0 );
132     // left-top
133     const fheroes2::Sprite & part4 = fheroes2::AGG::GetICN( buybuild, 4 );
134 
135     fheroes2::Display & display = fheroes2::Display::instance();
136 
137     fheroes2::Blit( part4, display, _position.x + overallLeftWidth - part4.width(), _position.y );
138     fheroes2::Blit( part0, display, _position.x + overallLeftWidth, _position.y );
139 
140     _position.y += part4.height();
141 
142     const int32_t posBeforeMiddle = _position.y;
143     int32_t middleLeftHeight = _middleFragmentHeight;
144     for ( uint32_t i = 0; i < _middleFragmentCount; ++i ) {
145         const int32_t chunkHeight = middleLeftHeight >= activeAreaHeight ? activeAreaHeight : middleLeftHeight;
146         // left-middle
147         const fheroes2::Sprite & sl = fheroes2::AGG::GetICN( buybuild, 5 );
148         fheroes2::Blit( sl, 0, 10, display, _position.x + overallLeftWidth - sl.width(), _position.y, sl.width(), chunkHeight );
149 
150         // right-middle
151         const fheroes2::Sprite & sr = fheroes2::AGG::GetICN( buybuild, 1 );
152         fheroes2::Blit( sr, 0, 10, display, _position.x + overallLeftWidth, _position.y, sr.width(), chunkHeight );
153 
154         middleLeftHeight -= chunkHeight;
155         _position.y += chunkHeight;
156     }
157 
158     _position.y = posBeforeMiddle + _middleFragmentHeight;
159 
160     // right-bottom
161     const fheroes2::Sprite & part2 = fheroes2::AGG::GetICN( buybuild, 2 );
162     // left-bottom
163     const fheroes2::Sprite & part6 = fheroes2::AGG::GetICN( buybuild, 6 );
164 
165     fheroes2::Blit( part6, display, _position.x + overallLeftWidth - part6.width(), _position.y );
166     fheroes2::Blit( part2, display, _position.x + overallLeftWidth, _position.y );
167 }
168 
~NonFixedFrameBox()169 Dialog::NonFixedFrameBox::~NonFixedFrameBox()
170 {
171     _restorer->restore();
172 
173     fheroes2::Display::instance().render();
174 }
175 
FrameBox(int height,bool buttons)176 Dialog::FrameBox::FrameBox( int height, bool buttons )
177     : Dialog::NonFixedFrameBox( height, -1, buttons )
178 {}
179