1 ////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // Nestopia - NES/Famicom emulator written in C++
4 //
5 // Copyright (C) 2003-2008 Martin Freij
6 //
7 // This file is part of Nestopia.
8 //
9 // Nestopia is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // Nestopia is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Nestopia; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 //
23 ////////////////////////////////////////////////////////////////////////////////////////
24 
25 #include "language/resource.h"
26 #include "NstApplicationException.hpp"
27 #include "NstWindowCustom.hpp"
28 #include "NstWindowParam.hpp"
29 #include "NstWindowStatusBar.hpp"
30 #include <CommCtrl.h>
31 
32 namespace Nestopia
33 {
34 	namespace Window
35 	{
Width(const uint n)36 		inline StatusBar::Width::Width(const uint n)
37 		: numChars(n) {}
38 
Calculate(HWND const hWnd)39 		void StatusBar::Width::Calculate(HWND const hWnd)
40 		{
41 			NST_ASSERT( hWnd );
42 
43 			character = DEF_CHAR_WIDTH;
44 			first = DEF_FIRST_WIDTH;
45 
46 			if (HDC const hDC = ::GetDC( hWnd ))
47 			{
48 				TEXTMETRIC tm;
49 
50 				if (::GetTextMetrics( hDC, &tm ))
51 					character = tm.tmAveCharWidth;
52 
53 				first = character * numChars;
54 
55 				::ReleaseDC( hWnd, hDC );
56 			}
57 		}
58 
StatusBar(Custom & p,const uint numChars)59 		StatusBar::StatusBar(Custom& p,const uint numChars)
60 		:
61 		width  ( numChars ),
62 		parent ( p )
63 		{
64 			static const MsgHandler::HookEntry<StatusBar> hooks[] =
65 			{
66 				{ WM_SIZE,    &StatusBar::OnSize    },
67 				{ WM_DESTROY, &StatusBar::OnDestroy }
68 			};
69 
70 			parent.Messages().Hooks().Add( this, hooks );
71 		}
72 
~StatusBar()73 		StatusBar::~StatusBar()
74 		{
75 			window.Destroy();
76 			parent.Messages().Hooks().Remove( this );
77 		}
78 
Enable(const bool enable,const bool show)79 		void StatusBar::Enable(const bool enable,const bool show)
80 		{
81 			NST_ASSERT( bool(parent) );
82 
83 			if (enable)
84 			{
85 				if (window == NULL)
86 				{
87 					window = CreateWindowEx
88 					(
89 						0,
90 						STATUSCLASSNAME,
91 						NULL,
92 						WS_CHILD|SBARS_SIZEGRIP|(show ? WS_VISIBLE : 0),
93 						0,0,0,0,
94 						parent,
95 						reinterpret_cast<HMENU>(CHILD_ID),
96 						::GetModuleHandle(NULL),
97 						NULL
98 					);
99 
100 					if (window == NULL)
101 						throw Application::Exception( IDS_ERR_FAILED, L"CreateWindowEx()" );
102 
103 					width.Calculate( window );
104 					Update();
105 				}
106 			}
107 			else
108 			{
109 				window.Destroy();
110 			}
111 		}
112 
OnDestroy(Param &)113 		void StatusBar::OnDestroy(Param&)
114 		{
115 			window.Destroy();
116 		}
117 
Show() const118 		void StatusBar::Show() const
119 		{
120 			window.Show();
121 		}
122 
operator <<(wcstring text) const123 		void StatusBar::Stream::operator << (wcstring text) const
124 		{
125 			if (window)
126 				window.Send( SB_SETTEXT, field|0, text );
127 		}
128 
Clear() const129 		void StatusBar::Stream::Clear() const
130 		{
131 			operator << (L"");
132 		}
133 
GetMaxMessageLength() const134 		uint StatusBar::GetMaxMessageLength() const
135 		{
136 			if (window)
137 			{
138 				int list[2] = {0,0};
139 				window.Send( SB_GETPARTS, 2, list );
140 
141 				if (list[0] > int(width.character))
142 					return uint(list[0]) / (width.character - 1);
143 			}
144 
145 			return 0;
146 		}
147 
Update() const148 		void StatusBar::Update() const
149 		{
150 			NST_ASSERT( window && parent );
151 
152 			int list[2] = { parent.ClientCoordinates().x - int(width.first), -1 };
153 			window.Send( SB_SETPARTS, 2, list );
154 		}
155 
OnSize(Param & param)156 		void StatusBar::OnSize(Param& param)
157 		{
158 			if (window)
159 			{
160 				window.Send( WM_SIZE, param.wParam, param.lParam );
161 				Update();
162 			}
163 		}
164 
Height() const165 		uint StatusBar::Height() const
166 		{
167 			if (window)
168 			{
169 				const int height = window.Coordinates().Height();
170 
171 				if (height > 0)
172 					return height;
173 			}
174 
175 			return 0;
176 		}
177 	}
178 }
179 
180