Jypeli  5
The simple game programming library
Label.cs
Siirry tämän tiedoston dokumentaatioon.
1 #region MIT License
2 /*
3  * Copyright (c) 2009-2011 University of Jyväskylä, Department of Mathematical
4  * Information Technology.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #endregion
25 
26 /*
27  * Authors: Tomi Karppinen, Tero Jäntti
28  */
29 
30 using System;
31 using System.Text;
32 using Microsoft.Xna.Framework;
33 using Microsoft.Xna.Framework.Graphics;
34 
35 namespace Jypeli.Widgets
36 {
37  public enum TextSizeMode
38  {
43  None,
44 
48  AutoSize,
49 
54 
58  Wrapped,
59  }
60 
61 
65  public class Label : BindableWidget
66  {
67  Font font;
68  string _title = "";
69  string originalText = "";
70  string visibleText = "";
71  TextSizeMode sizeMode = TextSizeMode.None;
72  int decimalPlaces = 2;
73  string doubleFormatString = "{0:N2}";
74  string intFormatString = "{0:D1}";
75  string doubleFormatStringWithTitle = "{0:N2}";
76  string intFormatStringWithTitle = "{0:D1}";
77  double _xMargin;
78  private double _yMargin;
79  bool useDefaultHeight = false;
80  bool initialized = false;
81 
82  const double DefaultWidth = 100;
83 
84  static double GetDefaultHeight()
85  {
86  Vector2 fontDims = Font.Default.XnaFont.MeasureString( "A" );
87  return fontDims.Y;
88  }
89 
93  public virtual string Text
94  {
95  get { return originalText; }
96  set
97  {
98  if ( value == null )
99  throw new ArgumentException( "Text must not be null" );
100  originalText = value;
101  updateSize();
102  }
103  }
104 
108  public bool IsTruncated
109  {
110  get { return visibleText.Length < ( originalText.Length ); }
111  }
112 
113  Vector3 _textScale = new Vector3(1, 1, 1);
114 
118  public Vector TextScale
119  {
120  get { return new Vector(_textScale.X, _textScale.Y); }
121  set
122  {
123  _textScale = new Vector3((float)value.X, (float)value.Y, 1.0f);
124  updateSize();
125  }
126  }
127 
128 
133  public int DecimalPlaces
134  {
135  get { return decimalPlaces; }
136  set
137  {
138  decimalPlaces = value;
139  DoubleFormatString = "{0:N" + decimalPlaces + "}";
140  }
141  }
142 
143 
147  public string DoubleFormatString
148  {
149  get { return doubleFormatString; }
150  set
151  {
152  doubleFormatString = value;
153  doubleFormatStringWithTitle = Title + ": " + value;
154  UpdateValue();
155  }
156  }
157 
158 
167  public string IntFormatString
168  {
169  get { return intFormatString; }
170  set
171  {
172  intFormatString = value;
173  intFormatStringWithTitle = Title + ": " + value;
174  UpdateValue();
175  }
176 
177  }
178 
183  public string Title
184  {
185  get
186  {
187  return _title;
188  }
189  set
190  {
191  _title = value;
192  intFormatStringWithTitle = _title == "" ? IntFormatString : value + ": " + IntFormatString;
193  doubleFormatStringWithTitle = _title == "" ? DoubleFormatString : value + ": " + DoubleFormatString;
194  }
195  }
196 
200  public TextSizeMode SizeMode
201  {
202  get { return sizeMode; }
203  set { sizeMode = value; updateSize(); }
204  }
205 
210  public Vector TextSize { get; private set; }
211 
215  public Color TextColor { get; set; }
216 
220  public Font Font
221  {
222  get { return font; }
223  set { font = value; updateSize(); }
224  }
225 
232 
239 
243  public double XMargin
244  {
245  get { return _xMargin; }
246  set { _xMargin = value; updateSize(); }
247  }
248 
252  public double YMargin
253  {
254  get { return _yMargin; }
255  set { _yMargin = value; updateSize(); }
256  }
257 
263  public override Vector Size
264  {
265  get
266  {
267  return base.Size;
268  }
269  set
270  {
271  if ( sizeMode == TextSizeMode.StretchText )
272  TextScale = new Vector( TextScale.X * value.X / base.Size.X, TextScale.Y * value.Y / base.Size.Y );
273 
274  useDefaultHeight = false;
275  base.Size = value;
276 
277  switch ( SizeMode )
278  {
279  case TextSizeMode.None:
280  TruncateText();
281  break;
282  case TextSizeMode.Wrapped:
283  WrapText();
284  break;
285  }
286  }
287  }
288 
293  public Label()
294  : this( DefaultWidth, 10 )
295  {
296  sizeMode = TextSizeMode.AutoSize;
297 
298  if ( Game.Instance != null )
299  {
300  this.Height = GetDefaultHeight();
301  updateSize();
302  }
303  else
304  Game.InstanceInitialized += setDefaultHeight;
305  }
306 
311  public Label( string text )
312  : this( DefaultWidth, 10, text )
313  {
314  sizeMode = TextSizeMode.AutoSize;
315 
316  if ( Game.Instance != null )
317  {
318  this.Height = GetDefaultHeight();
319  updateSize();
320  }
321  else
322  Game.InstanceInitialized += setDefaultHeight;
323  }
324 
329  public Label(Meter meter)
330  : this()
331  {
332  this.BindTo(meter);
333  }
334 
338  public Label( Animation animation )
339  : base( animation )
340  {
341  Game.AssertInitialized( Initialize );
342  }
343 
349  public Label( double width, double height )
350  : this( width, height, "" )
351  {
352  }
353 
360  public Label( double width, double height, string text )
361  : base( width, height, Shape.Rectangle )
362  {
363  this.sizeMode = TextSizeMode.None;
364  this.originalText = text;
365  Game.AssertInitialized( Initialize );
366  }
367 
368  private void setDefaultHeight()
369  {
370  if ( !useDefaultHeight ) return;
371  this.Height = GetDefaultHeight();
372  }
373 
374  private void Initialize()
375  {
376  font = Font.Default;
378  TextColor = Color.Black;
381  updateSize();
382  initialized = true;
383  UpdateValue();
384  }
385 
386  protected override void UpdateValue()
387  {
388  if ( !initialized || !Bound ) return;
389 
390  if ( Meter is IntMeter )
391  {
392  int newNumber = ( (IntMeter)Meter ).Value;
393  Text = string.Format( intFormatString, newNumber );
394  }
395  else if ( Meter is DoubleMeter )
396  {
397  double newNumber = ( (DoubleMeter)Meter ).Value;
398  Text = string.Format( doubleFormatString, newNumber );
399  }
400  }
401 
405  private void updateSize()
406  {
407  SpriteFont xnaFont = this.Font.XnaFont;
408  visibleText = (_title.Length > 0) ? (_title + ": " + originalText) : originalText;
409 
410  if ( visibleText.Length == 0 )
411  {
412  this.TextSize = Vector.Zero;
413  NotifyParentAboutChangedSizingAttributes();
414  return;
415  }
416 
417  Vector2 rawTextDims = xnaFont.MeasureString( visibleText );
418  Vector2 fullTextDims = new Vector2( _textScale.X * rawTextDims.X, _textScale.Y * rawTextDims.Y );
419 
420  TextSize = new Vector( fullTextDims.X, fullTextDims.Y );
421 
422  switch ( SizeMode )
423  {
424  case TextSizeMode.None:
425  TruncateText();
426  break;
427 
428  case TextSizeMode.AutoSize:
429  base.Size = PreferredSize = new Vector( fullTextDims.X + 2 * XMargin, fullTextDims.Y + 2 * YMargin );
430  break;
431 
432  case TextSizeMode.Wrapped:
433  WrapText();
434  break;
435  }
436 
437  NotifyParentAboutChangedSizingAttributes();
438  }
439 
440  private void TruncateText()
441  {
442  double textWidth = this.Width - 2 * XMargin;
443  if ( textWidth <= 0 )
444  {
445  textWidth = this.Width;
446  }
447 
448  visibleText = font.TruncateText( Text, textWidth );
449 
450  Vector2 textDims = Font.XnaFont.MeasureString( visibleText );
451  TextSize = new Vector( textDims.X, textDims.Y );
452  }
453 
454  private void WrapText()
455  {
456  SpriteFont xnaFont = this.Font.XnaFont;
457  Vector2 rawTextDims = xnaFont.MeasureString( visibleText );
458  Vector2 fullTextDims = new Vector2( _textScale.X * rawTextDims.X, _textScale.Y * rawTextDims.Y );
459 
460  if ( Width <= 0 || fullTextDims.X <= Width )
461  return;
462 
463  double hardBreak = base.Size.X - 2 * XMargin;
464  double softBreak = Math.Max( hardBreak / 2, hardBreak - 5 * Font.CharacterWidth );
465 
466  visibleText = Font.WrapText( visibleText, hardBreak, softBreak );
467  Vector2 textDims = xnaFont.MeasureString( visibleText );
468  base.Size = PreferredSize = new Vector( base.Size.X, textDims.Y + 2 * YMargin );
469  TextSize = new Vector( textDims.X, textDims.Y );
470  }
471 
472  private double GetHorizontalAlignment()
473  {
474  switch ( HorizontalAlignment )
475  {
476  case HorizontalAlignment.Center:
477  return -TextSize.X / 2;
478  case HorizontalAlignment.Left:
479  return -Width / 2 + XMargin;
480  case HorizontalAlignment.Right:
481  return Width / 2 - TextSize.X - XMargin;
482  default:
483  return XMargin;
484  }
485  }
486 
487  private double GetVerticalAlignment()
488  {
489  switch ( VerticalAlignment )
490  {
491  case VerticalAlignment.Center:
492  return -TextSize.Y / 2;
493  case VerticalAlignment.Top:
494  return -Size.Y / 2 - YMargin;
495  case VerticalAlignment.Bottom:
496  return Size.Y / 2 - TextSize.Y + YMargin;
497  default:
498  return -YMargin;
499  }
500  }
501 
502  protected override void Draw( Matrix parentTransformation, Matrix transformation )
503  {
504  Draw( parentTransformation, transformation, visibleText );
505  }
506 
507  protected void Draw( Matrix parentTransformation, Matrix transformation, string text )
508  {
509  // Reverse the Y axis of the parent transformation
510  Matrix p = parentTransformation;
511  p.Translation = new Vector3( p.Translation.X, -p.Translation.Y, p.Translation.Z );
512 
513  Matrix m =
514  Matrix.CreateScale( _textScale )
515  * Matrix.CreateTranslation( (float)GetHorizontalAlignment(), (float)GetVerticalAlignment(), 0 )
516  * Matrix.CreateRotationZ( (float)-Angle.Radians )
517  * Matrix.CreateTranslation( (float)Position.X, -(float)Position.Y, 0 )
518  * p
519  * Matrix.CreateTranslation( (float)( Game.Screen.Width / 2 ), (float)( Game.Screen.Height / 2 ), 0 );
520 
521  Renderer.DrawText( text, ref m, Font, TextColor );
522 
523  base.Draw( parentTransformation, transformation );
524  }
525  }
526 }
HorizontalAlignment
Asemointi vaakasuunnassa.
Definition: View.cs:177
static Action InstanceInitialized
Tapahtuu kun Game.Instance on alustettu.
Definition: Game.cs:154
Kuvio.
Definition: Shapes.cs:48
static readonly Color Black
Musta.
Definition: Color.cs:494
override void Draw(Matrix parentTransformation, Matrix transformation)
Definition: Label.cs:502
string WrapText(string text, double softLineWidth, double hardLineWidth)
Rivittää tekstin.
Definition: Font.cs:162
Suuntakulma (rajoitettu -180 ja 180 asteen välille) asteina ja radiaaneina. Tietoja kulmasta: http://...
Definition: Angle.cs:40
Teksti rivitetään tekstikentän leveyden mukaan.
Fontti.
Definition: Font.cs:22
Suorakulmio.
Definition: Shapes.cs:315
double CharacterWidth
Merkin leveys.
Definition: Font.cs:68
Widget, joka voidaan asettaa näyttämään halutun mittarin arvoa.
Label(Meter meter)
Lue uuden tekstikentän ja sitoo sen mittarin arvoon.
Definition: Label.cs:329
string TruncateText(string str, double maxLineWidth)
Katkaisee merkkijonon loppupäästä niin että se sopii annettuun pikselileveyteen fontilla kirjoitettun...
Definition: Font.cs:135
Tekstikenttä.
Definition: Label.cs:65
static Game Instance
Definition: Game.cs:149
static readonly Vector Zero
Nollavektori.
Definition: Vector.cs:61
Mittari, joka mittaa double-tyyppisiä arvoja. Sidottavissa näyttöihin, kuten ValueDisplay ja BarGauge...
Definition: Meter.cs:515
Label(Animation animation)
Luo uuden tekstikentän animaatiolla.
Definition: Label.cs:338
Tekstikentän koko asetetaan tekstin koon mukaan.
double Height
Näytön korkeus y-suunnassa.
Definition: View.cs:74
Tekstin koko asetetaan tekstikentän koon mukaan.
static ScreenView Screen
Näytön dimensiot, eli koko ja reunat.
Definition: Game.cs:194
static readonly Color Transparent
Läpinäkyvä väri.
Definition: Color.cs:869
Label(double width, double height)
Luo uuden tekstikentän.
Definition: Label.cs:349
Peliluokka reaaliaikaisille peleille.
Definition: DebugScreen.cs:10
void Draw(Matrix parentTransformation, Matrix transformation, string text)
Definition: Label.cs:507
Mittari, joka mittaa int-tyyppisiä arvoja. Sidottavissa näyttöihin, kuten ValueDisplay ja BarGauge...
Definition: Meter.cs:387
double Radians
Palauttaa tai asettaa kulman radiaaneina.
Definition: Angle.cs:86
Label(string text)
Luo uuden tekstikentän annetulla tekstillä. Asettaa koon tekstin mukaan.
Definition: Label.cs:311
static readonly Font Default
OletusFontti.
Definition: Font.cs:27
Label(double width, double height, string text)
Luo uuden tekstikentän.
Definition: Label.cs:360
Väri.
Definition: Color.cs:13
VerticalAlignment
Asemointi pystysuunnassa.
Definition: View.cs:198
Sarja kuvia, jotka vaihtuvat halutulla nopeudella. Yksi animaatio koostuu yhdestä tai useammasta kuva...
Definition: Animation.cs:56
Luokka, joka sisältää metodeita kuvioiden ja tekstuurien piirtämiseen 2D-tasossa. ...
Definition: Renderer.cs:51
2D-vektori.
Definition: Vector.cs:56
double Width
Näytön leveys x-suunnassa.
Definition: View.cs:66
static void AssertInitialized(Action actionMethod)
Suorittaa aliohjelman kun peli on varmasti alustettu.
Definition: Game.cs:630
Label()
Luo uuden tekstikentän. Asettaa koon tekstin mukaan.
Definition: Label.cs:293
Mittari, joka mittaa erityyppisiä arvoja. Sidottavissa näyttöihin, kuten ValueDisplay ja BarGauge...
Definition: Meter.cs:60
override void UpdateValue()
Kutsutaan automaattisesti, kun mittarin arvo on muuttunut. Ylikirjoita tämä koodilla, joka muuttaa widgetin ulkonäköä asianmukaisesti.
Definition: Label.cs:386