1 /*************************************************************************** 2 blatt.h - description 3 ------------------- 4 begin : Mit Jul 12 22:54:51 MEST 2000 5 copyright : (C) 2006 by Immi 6 email : cuyo@pcpool.mathematik.uni-freiburg.de 7 8 Modified 2006,2008,2010,2011 by the cuyo developers 9 10 ***************************************************************************/ 11 12 /*************************************************************************** 13 * * 14 * This program is free software; you can redistribute it and/or modify * 15 * it under the terms of the GNU General Public License as published by * 16 * the Free Software Foundation; either version 2 of the License, or * 17 * (at your option) any later version. * 18 * * 19 ***************************************************************************/ 20 21 #ifndef BLATT_H 22 #define BLATT_H 23 24 #include <vector> 25 #include <SDL.h> 26 27 #include "stringzeug.h" 28 #include "inkompatibel.h" 29 #include "punktefeld.h" 30 31 #include "leveldaten.h" // wegen grx, gry, max_spielerzahl; sollte woanders hin 32 33 34 35 enum { 36 blattpic_pfeile, 37 blattpic_highlight, 38 blattpic_titel, 39 blattpic_scroll, 40 blattpic_scrollbright, 41 blattpic_scrolldimmed, 42 blattpic_border, 43 blattpic_borderh, 44 blattpic_borderv, 45 blattpic_infoicons, 46 anz_blattpics 47 }; 48 49 /* Men�punkte werden an verschiedenen Linien zentriert. Die Positionen 50 dieser Linien werden getrennt berechnet. Siehe BlattMenu::oeffnen */ 51 enum ZentrierLinie { 52 zl_zentriert, zl_accel, zl_daten, zl_anzahl 53 }; 54 55 56 class BlattMenu; 57 58 59 class Blatt { 60 61 public: ~Blatt()62 virtual ~Blatt() {} 63 64 virtual void doEvent(const SDL_Event & evt); keyEvent(const SDL_keysym &)65 virtual void keyEvent(const SDL_keysym & ) {} resizeEvent()66 virtual void resizeEvent() {} mouseButtonEvent(bool,int,int)67 virtual void mouseButtonEvent(bool , int , int ) {} mouseMotionEvent(bool,int,int,int,int)68 virtual void mouseMotionEvent(bool , int , int , int , int) {} 69 virtual void anzeigen() = 0; 70 zeitSchritt()71 virtual void zeitSchritt() {} 72 73 /* Global-Zeug */ 74 static Bilddatei * gBlattPics[anz_blattpics]; 75 76 static void initBlaetter(); 77 static void destroyBlaetter(); 78 }; 79 80 81 82 83 class BlattSpiel: public Blatt { 84 85 /** Die Punkte-Anzeigen */ 86 Punktefeld * mPunktefeld[max_spielerzahl]; 87 bool mDekoUpdaten; 88 89 public: 90 BlattSpiel(); 91 ~BlattSpiel(); 92 93 virtual void oeffnen(int lnr); 94 virtual void keyEvent(const SDL_keysym & taste); 95 virtual void resizeEvent(); 96 virtual void anzeigen(); 97 virtual void zeitSchritt(); 98 99 void randNeuMalen(); 100 void setPunkte(int sp, int pt); 101 102 private: 103 void malInfos(int sp, int x); 104 }; 105 106 107 108 109 110 class MenuEintrag; 111 112 113 /* Konstanten f�r mausbereich.mEintrag */ 114 #define eintrag_keiner (-1) 115 #define eintrag_scrollleiste (-2) 116 117 /* Der einzige Subbereich, der f�r Tastatur-User existiert. */ 118 #define subbereich_default 0 119 /* Die folgenden Konstanten sind nur zur �bergabe von oder an 120 Funktionen und nicht zum Speichern in einem MausBereich. */ 121 #define subbereich_hyperaktiv (-2) 122 #define subbereich_keiner (-1) 123 #define subbereich_keinStrom (-3) 124 #define subbereich_nichtInitialisiert (-4) 125 126 struct MausBereich { 127 128 int mEintrag; 129 /* Die Bedeutung von subbereich h�ngt von der Men�eintragart ab. 130 Subbereich ist nur f�r Maususer. Aus Sicht von Tastatur-Usern 131 gibt es nur den default-Subbereich. (Sobald eine Taste gedr�ckt 132 wird, sollte auch wieder dort hin geschaltet werden.) */ 133 int mSubBereich; 134 MausBereichMausBereich135 MausBereich(): mEintrag(eintrag_keiner) {} MausBereichMausBereich136 explicit MausBereich(int e): mEintrag(e), mSubBereich(subbereich_default) {} MausBereichMausBereich137 MausBereich(int e, int sb): mEintrag(e), mSubBereich(sb) {} 138 139 bool operator==(const MausBereich & m) const { 140 if (mEintrag != m.mEintrag) 141 return false; 142 if (mEintrag == eintrag_keiner) 143 return true; 144 return mSubBereich == m.mSubBereich; 145 } 146 }; 147 148 149 150 class MenuEintragSubmenu; 151 152 enum yneuwahl { /* Zur �bergabe an calcScroll(): 153 wo (vertikal) soll der mWahl-Eintrag stehen? */ 154 ynw_mitte, 155 ynw_oben, 156 ynw_unten 157 }; 158 159 class BlattMenu: public Blatt { 160 friend struct DrawDing; 161 friend class MenuEintrag; /* Damit Men�punkte doEscape() aufrufen k�nnen */ 162 163 protected: 164 /* Soll es auch dann eine Scrollleiste haben, wenn sie unn�tig ist? 165 (=> hat auch escape-button) */ 166 bool mImmerScrollleiste; 167 std::vector<MenuEintrag*> mEintraege; 168 std::vector<int> mEintraegeY; /* relativ zu mY0. 169 Geht eins weiter als mEintraege, 170 so da� es auch die Gesamth�he enth�lt. */ 171 BlattMenu * mObermenu; /* NULL f�r das Hauptmen� */ 172 173 /* Wenn der Eintrag, wo dies ein Untermen� ist, erfahren m�chte, wenn 174 das Men� verlassen wird, sollte er sich mit setObereintrag() hier 175 eintragen. */ 176 MenuEintragSubmenu * mObereintrag; 177 178 /* Wenn was Hyperaktiv ist, kann mWahl trotzdem ein anderer Men�punkt 179 sein: wenn sich die Maus �ber einem anderen Men�punkt befindet. 180 (Tastendr�cke gehen dann aber an den hyperaktiven Eintrag) */ 181 MausBereich mWahl; 182 /* True, wenn Button unten; wird (im Moment) nur f�r Scrollleistenpfeile 183 gebraucht. */ 184 bool mPress; 185 int mHyperaktiv; // eintrag_keiner wenn nix hyperaktiv ist 186 Str mInfoText; 187 int mInfoW; // negativ f�r "kein Scrollen", sonst Textbreite 188 int mInfoX; /* current position of scrolling info text. 189 Can be negative. In fact, the scrolling text is drawn 190 twice: This is the left copy, the right one starts 191 at mInfox+mInfoW. */ 192 193 /* mX0 = x-Koordinate f�rs alignen... getrennt nach 194 mY0 = y-Koordinate vom oberen Rand von Men�punkt 0 195 (evtl. weit oberhalb vom Bildschirm) */ 196 int mX0[zl_anzahl], mY0, mZeigVon, mZeigBis; 197 /* mAnimXX: Wie ohne Anim, aber tats�chliche Position w�hrend einer 198 Scroll-Animation (im Gegensatz zu: Zielposition) */ 199 int mAnimY0, mAnimZeigVon, mAnimZeigBis; 200 /* Aktuelle Scrollgeschwindigkeit */ 201 int mScrollGesch; 202 203 bool mRahmenUpdaten; 204 bool mRaenderUpdaten; 205 bool mInfozeileUpdaten; 206 207 public: 208 explicit BlattMenu(bool immerscrollleiste = false); 209 virtual ~BlattMenu(); 210 /* Gleich nach dem Konstruktor aufrufen, wenn das Obermenu nicht NULL 211 sein soll. Schoener waers, obermenu direkt dem Konstruktor zu 212 uebergeben. Das wuerde aber bedeuten, dass man gezwungen ist, in 213 *jeder* Klasse, die von BlattMenu erbt, einen Konstruktor zu 214 schreiben. Liefert einfach this zurueck, damit man 215 (new BlattMenuXXX())->setObermenu(...) 216 schreiben kann */ 217 BlattMenu * setObermenu(BlattMenu * obermenu); 218 void setObereintrag(MenuEintragSubmenu * obereintrag); 219 220 void neuerEintrag(MenuEintrag*); 221 222 virtual void oeffnen(bool durchMaus, int wahl = eintrag_keiner); 223 virtual void keyEvent(const SDL_keysym & taste); 224 virtual void mouseButtonEvent(bool press, int x, int y); 225 virtual void mouseMotionEvent(bool press, int x, int y, int x_alt, int y_alt); 226 virtual void resizeEvent(); 227 virtual void anzeigen(); 228 virtual void zeitSchritt(); 229 230 protected: 231 virtual void doEscape(); 232 virtual void doReturn(bool durchMaus); 233 234 void menuLoeschen(); 235 236 /* �ndert mWahl und k�mmert sich drum, dass Graphik geupdatet wird */ 237 void setWahl(MausBereich wahl); 238 void setWahl(int eintrag, int subBereich = subbereich_default); 239 240 /* �ndert mHyperaktiv und k�mmert sich drum, dass Graphik geupdatet wird */ 241 void setHyperaktiv(int ha); 242 243 /* K�mmert sich um mInfotext und mInfoY. 244 Wird aufgerufen, wenn sich mInfotext vielleicht �ndern soll. 245 Also unter anderem von setWahl() und setHyperaktiv() */ 246 void updateInfo(); 247 248 /* Teilt dem Eintrag seinen neuen Subbereich mit. Der Eintrag k�mmert 249 sich dann um sein Graphik-Update */ 250 void updateEintrag(int e); 251 252 void sichtbaresUpdaten(); 253 254 bool istScrollbar() const; 255 256 void scrollleisteScroll(int sgn); 257 258 /* Gleicht mY0, mZeigVon und mZeigBis an mWahl an. 259 sprung = true => keine Animation, sondern direkt dort hin. */ 260 void setScrollZielHigh(yneuwahl = ynw_mitte, bool sprung = false); 261 262 /* Setzt mY0 und gleicht mZeigVon und mZeigBis an. 263 sprung = true => keine Animation, sondern direkt dort hin. */ 264 void setScrollZielLow(int neuy, bool sprung = false); 265 266 void scrollZeitSchritt(); 267 268 /* Berechnet zeigVon und zeigBis aus Y0... mit oder ohne anim */ 269 void calcZeigVonBis(int y0, int & von, int & bis); 270 271 private: 272 void navigiere(int d, int vorschlag = -1); 273 274 MausBereich getMausPos(int x, int y); 275 276 /* Wo befindet sich der Cursor aus Sicht von Tastatur-Usern? */ 277 int getTastenCursorPos(); 278 }; 279 280 281 282 283 class BlattStartAt: public BlattMenu { 284 285 public: BlattStartAt()286 BlattStartAt(): BlattMenu(true) {} /* true: Scrollleiste immer da... und esc-Button */ 287 288 virtual void oeffnen(bool durchMaus, int wahl = eintrag_keiner); 289 /* Hier wird der int ignoriert, da sich die Klasse selbst drum k�mmert */ 290 protected: 291 virtual void doReturn(bool durchMaus); 292 }; 293 294 295 296 297 298 class BlattHauptmenu: public BlattMenu { 299 300 public: 301 BlattHauptmenu(); 302 }; 303 304 305 306 class BlattPrefs: public BlattMenu { 307 308 public: 309 BlattPrefs(); 310 311 protected: 312 virtual void doEscape(); 313 }; 314 315 316 317 318 319 320 #endif 321