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 #ifndef NST_WINDOW_MENU_H 26 #define NST_WINDOW_MENU_H 27 28 #pragma once 29 30 #include "language/resource.h" 31 #include "NstResourceMenu.hpp" 32 #include "NstSystemAccelerator.hpp" 33 #include "NstWindowCustom.hpp" 34 35 namespace Nestopia 36 { 37 namespace Window 38 { 39 class Menu 40 { 41 public: 42 43 explicit Menu(uint); 44 ~Menu(); 45 46 void Hook(Custom&); 47 void Unhook(); 48 uint Height() const; 49 bool Visible() const; 50 void Show(bool=true) const; 51 bool Toggle() const; 52 void EnableAccelerator(bool); 53 void SetKeys(const ACCEL*,uint); 54 void SetColor(COLORREF) const; 55 void ResetColor() const; 56 void ToggleModeless(bool) const; 57 58 class Item; 59 60 void Insert(const Item&,uint,GenericString) const; 61 62 private: 63 64 static void Clear(HMENU); 65 static uint NumItems(HMENU); 66 static void Redraw(const Custom*); 67 68 public: 69 Redraw() const70 void Redraw() const 71 { 72 Redraw( window ); 73 } 74 75 class Item 76 { 77 friend class Menu; 78 79 class Stream 80 { 81 friend class Menu; 82 friend class Item; 83 84 const Item& item; 85 86 uint GetLength() const; 87 bool GetFullString(wchar_t*,uint) const; 88 void SetFullString(wcstring) const; 89 90 template<typename T> GetFullString(T & string) const91 void GetFullString(T& string) const 92 { 93 string.Resize( GetLength() ); 94 GetFullString( string.Ptr(), string.Length() ); 95 } 96 Stream(const Item & i)97 explicit Stream(const Item& i) 98 : item(i) {} 99 100 public: 101 102 void operator << (const GenericString&) const; 103 104 template<typename T> operator >>(T & string) const105 uint operator >> (T& string) const 106 { 107 GetFullString( string ); 108 string.FirstOf( '\t' ).Clear(); 109 return string.Length(); 110 } 111 }; 112 113 public: 114 115 enum Type 116 { 117 NONE, 118 SUBMENU, 119 COMMAND, 120 SEPARATOR 121 }; 122 123 Type GetType() const; 124 125 bool Enable (bool=true) const; 126 bool Check (bool=true) const; 127 void Check (uint,uint,bool) const; 128 void Check (uint,uint) const; 129 130 bool Enabled () const; 131 bool Checked () const; 132 Disabled() const133 bool Disabled () const { return !Enabled(); } Unchecked() const134 bool Unchecked () const { return !Checked(); } 135 ToggleCheck() const136 bool ToggleCheck() const { return !Check( Unchecked() ); } ToggleEnable() const137 bool ToggleEnable() const { return !Enable( Disabled() ); } 138 Disable() const139 bool Disable () const { return Enable (false); } Uncheck() const140 bool Uncheck () const { return Check (false); } 141 142 uint GetCommand() const; 143 void Remove() const; 144 void Clear() const; 145 uint NumItems() const; 146 bool Exists() const; 147 Text() const148 Stream Text() const 149 { 150 return Stream( *this ); 151 } 152 153 private: 154 155 inline uint Flag() const; 156 157 HMENU hMenu; 158 uint pos; 159 const Custom* const window; 160 161 public: 162 Item(const Custom * w,HMENU h=NULL,uint p=0)163 Item(const Custom* w,HMENU h=NULL,uint p=0) 164 : hMenu(h), pos(p), window(w) {} 165 GetHandle() const166 HMENU GetHandle() const 167 { 168 return hMenu; 169 } 170 operator [](uint subPos) const171 Item operator [] (uint subPos) const 172 { 173 return Item( window, ::GetSubMenu( hMenu, pos ), subPos ); 174 } 175 }; 176 177 typedef Collection::Router<void,uint> CmdHandler; 178 179 class PopupHandler 180 { 181 friend class Menu; 182 183 struct Key 184 { 185 HMENU const hKey; 186 const Item item; 187 KeyNestopia::Window::Menu::PopupHandler::Key188 Key(const Custom* w,HMENU h,uint p) 189 : hKey(::GetSubMenu(h,p)), item(w,h,p) {} 190 KeyNestopia::Window::Menu::PopupHandler::Key191 explicit Key(WPARAM wParam) 192 : hKey(reinterpret_cast<HMENU>(wParam)), item(NULL) {} 193 operator HMENUNestopia::Window::Menu::PopupHandler::Key194 operator HMENU() const 195 { 196 return hKey; 197 } 198 }; 199 200 Menu& menu; 201 202 public: 203 204 template<uint A,uint B=UINT_MAX,uint C=UINT_MAX,uint D=UINT_MAX> struct Pos 205 { 206 enum { ID = A | (B + 1) << 8 | (C + 2) << 16 | (D + 3) << 24 }; 207 }; 208 209 template<uint A> struct Pos<A,UINT_MAX,UINT_MAX,UINT_MAX> 210 { 211 enum { ID = A }; 212 }; 213 214 template<uint A,uint B> struct Pos<A,B,UINT_MAX,UINT_MAX> 215 { 216 enum { ID = A | (B + 1) << 8 }; 217 }; 218 219 template<uint A,uint B,uint C> struct Pos<A,B,C,UINT_MAX> 220 { 221 enum { ID = A | (B + 1) << 8 | (C + 2) << 16 }; 222 }; 223 224 struct Param 225 { 226 Item menu; 227 bool show; 228 ParamNestopia::Window::Menu::PopupHandler::Param229 Param(const Item& i,bool s) 230 : menu(i), show(s) {} 231 }; 232 233 template<typename Data> struct Entry 234 { 235 typedef void (Data::*Function)(const Param&); 236 237 uint id; 238 Function function; 239 }; 240 241 private: 242 243 typedef Collection::Router<void,const Param&,Key> Handler; 244 245 Key GetKey(uint) const; 246 247 template<typename Data> 248 void Add(Data*,const Entry<Data>*,uint); 249 PopupHandler(Menu & m)250 PopupHandler(Menu& m) 251 : menu(m) {} 252 253 public: 254 255 template<typename Data,uint COUNT> Add(Data * data,const Entry<Data> (& list)[COUNT])256 void Add(Data* data,const Entry<Data>(&list)[COUNT]) 257 { 258 Add( data, list, COUNT ); 259 } 260 Remove(const void * data)261 void Remove(const void* data) 262 { 263 menu.popupHandler.Hooks().Remove( data ); 264 } 265 }; 266 267 private: 268 269 ibool OnCommand (Param&); 270 ibool OnInitMenuPopup (Param&); 271 ibool OnUninitMenuPopup (Param&); 272 void OnCreate (Param&); 273 void OnDestroy (Param&); 274 275 enum {IDM_OFFSET = 100}; 276 277 Resource::Menu handle; 278 Custom* window; 279 System::Accelerator accelerator; 280 CmdHandler cmdHandler; 281 MsgHandler::Callback cmdCallback; 282 PopupHandler::Handler popupHandler; 283 bool acceleratorEnabled; 284 285 class Instances 286 { 287 public: 288 289 static void Update(Menu*); 290 static void Remove(Menu*); 291 static void EnableAccelerators(bool); 292 293 private: 294 295 static void Update(); 296 static bool TranslateNone (MSG&); 297 static bool TranslateSingle (MSG&); 298 static bool TranslateMulti (MSG&); 299 300 typedef Collection::Vector<const Menu*> Menus; 301 typedef bool (*Translator)(MSG&); 302 303 static Translator translator; 304 static Menus menus; 305 static bool acceleratorsEnabled; 306 307 public: 308 TransAccelerator(MSG & msg)309 static bool TransAccelerator(MSG& msg) 310 { 311 return translator( msg ); 312 } 313 }; 314 315 public: 316 GetHandle() const317 HMENU GetHandle() const 318 { 319 return handle; 320 } 321 NumItems() const322 uint NumItems() const 323 { 324 return NumItems( handle ); 325 } 326 operator [](uint pos) const327 Item operator [] (uint pos) const 328 { 329 return Item( window, handle, pos ); 330 } 331 Hide() const332 void Hide() const 333 { 334 Show( false ); 335 } 336 Clear() const337 void Clear() const 338 { 339 Clear( handle ); 340 } 341 Commands()342 CmdHandler& Commands() 343 { 344 return cmdHandler; 345 } 346 Popups()347 PopupHandler Popups() 348 { 349 return *this; 350 } 351 TransAccelerator(MSG & msg)352 static bool TransAccelerator(MSG& msg) 353 { 354 return Instances::TransAccelerator( msg ); 355 } 356 EnableAccelerators(bool enable)357 static void EnableAccelerators(bool enable) 358 { 359 Instances::EnableAccelerators( enable ); 360 } 361 }; 362 363 template<typename Data> Add(Data * const data,const Entry<Data> * list,const uint count)364 void Menu::PopupHandler::Add(Data* const data,const Entry<Data>* list,const uint count) 365 { 366 for (const Entry<Data>* const end = list + count; list != end; ++list) 367 menu.popupHandler.Hooks().Add( GetKey(list->id), data, list->function ); 368 } 369 } 370 } 371 372 #endif 373