1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Windows.API;
  8 
  9 namespace System.Windows
 10 {
 11     public enum LabelStyle : long
 12     {
 13         SS_BITMAP = 0x000E
 14         SS_BLACKFRAME = 0x0007
 15         SS_BLACKRECT = 0x0004
 16         SS_CENTER = 0x0001
 17         SS_CENTERIMAGE = 0x0200
 18         SS_EDITCONTROL = 0x2000
 19         SS_ENDELLIPSIS = 0x4000
 20         SS_ENHMETAFILE = 0x000F
 21         SS_ETCHEDFRAME = 0x0012
 22         SS_ETCHEDHORZ = 0x0010
 23         SS_ETCHEDVERT = 0x0011
 24         SS_GRAYFRAME = 0x0008
 25         SS_GRAYRECT = 0x0005
 26         SS_ICON = 0x0003
 27         SS_LEFT = 0x0000
 28         SS_LEFTNOWORDWRAP = 0x000C
 29         SS_NOPREFIX = 0x0080
 30         SS_NOTIFY = 0x0100
 31         SS_OWNERDRAW = 0x000D
 32         SS_PATHELLIPSIS = 0x8000
 33         SS_REALSIZECONTROL = 0x0040
 34         SS_REALSIZEIMAGE = 0x0800
 35         SS_RIGHT = 0x0002
 36         SS_RIGHTJUST = 0x0400
 37         SS_SIMPLE = 0x000B
 38         SS_SUNKEN = 0x1000
 39         SS_TYPEMASK = 0x001F
 40         SS_WHITEFRAME = 0x0009
 41         SS_WHITERECT = 0x0006
 42         SS_WORDELLIPSIS = 0xC000
 43     }
 44 
 45     public nothrow ControlCreateParams& LabelControlCreateParams(ControlCreateParams& controlCreateParamsLabelStyle labelStyle)
 46     {
 47         return controlCreateParams.SetWindowClassName("STATIC").SetWindowStyle(cast<WindowStyle>(DefaultChildWindowStyle() | labelStyle));
 48     }
 49 
 50     public nothrow ControlCreateParams& LabelControlCreateParams(ControlCreateParams& controlCreateParams)
 51     {
 52         return LabelControlCreateParams(controlCreateParamsLabelStyle.SS_LEFT);
 53     }
 54 
 55     public class LabelCreateParams
 56     {
 57         public nothrow LabelCreateParams(ControlCreateParams& controlCreateParams_) : controlCreateParams(controlCreateParams_)autoSize(true)
 58         {
 59         }
 60         public nothrow LabelCreateParams& Defaults()
 61         {
 62             return *this;
 63         }
 64         public nothrow LabelCreateParams& SetAutoSize(bool autoSize_)
 65         {
 66             autoSize = autoSize_;
 67             return *this;
 68         }
 69         public ControlCreateParams& controlCreateParams;
 70         public bool autoSize;
 71     }
 72 
 73     public class Label : Control
 74     {
 75         private enum Flags : sbyte
 76         {
 77             none = 0autoSize = 1 << 0autoSized = 1 << 1
 78         }
 79 
 80         public Label(LabelStyle labelStyleconst Color& backgroundColorconst string& textconst Point& locationconst Size& size
 81             Dock dockAnchors anchorsbool autoSize) : 
 82             base("STATIC"DefaultWindowClassStyle()cast<WindowStyle>(DefaultChildWindowStyle() | labelStyle)DefaultExtendedWindowStyle()
 83             backgroundColortextlocationsizedockanchors)flags(Flags.none)
 84         {
 85             if (autoSize)
 86             {
 87                 SetAutoSizeFlag();
 88                 DoAutoSize();
 89             }
 90         }
 91         public Label(const string& textconst Point& locationconst Size& sizeDock dockAnchors anchorsbool autoSize) : 
 92             this(LabelStyle.SS_LEFTDefaultControlBackgroundColor()textlocationsizedockanchorsautoSize)
 93         {
 94         }
 95         public Label(LabelCreateParams& createParams) : base(createParams.controlCreateParams)flags(Flags.none)
 96         {
 97             if (createParams.autoSize)
 98             {
 99                 SetAutoSizeFlag();
100                 DoAutoSize();
101             }
102         }
103         protected override void OnCreated()
104         {
105             base->OnCreated();
106             Graphics graphics = Graphics.FromWindowHandle(Handle());
107             const FontHandle& fontHandle = GetFontHandle(graphics);
108             if (!fontHandle.IsNull())
109             {
110                 SendSetFontMessage(fontHandle);
111             }
112             if (AutoSize())
113             {
114                 DoAutoSize();
115             }
116         }
117         protected override void OnTextChanged()
118         {
119             base->OnTextChanged();
120             if (AutoSize())
121             {
122                 ResetAutoSized();
123                 DoAutoSize();
124             }
125         }
126         public inline nothrow bool AutoSize() const
127         {
128             return (flags & Flags.autoSize) != Flags.none;
129         }
130         public void SetAutoSize(bool autoSize)
131         {
132             if (autoSize)
133             {
134                 if (!AutoSize())
135                 {
136                     SetAutoSizeFlag();
137                     if (!AutoSized())
138                     {
139                         DoAutoSize();
140                     }
141                 }
142             }
143             else
144             {
145                 ResetAutoSizeFlag();
146                 ResetAutoSized();
147             }
148         }
149         private void DoAutoSize()
150         {
151             if (AutoSized()) return;
152             if (Handle() == null) return;
153             Graphics graphics = Graphics.FromWindowHandle(Handle());
154             const Font& font = GetFont();
155             StringFormat stringFormat;
156             RectF r = graphics.MeasureStringChecked(Text()fontPointF(00)stringFormat);
157             SetSize(Size(cast<int>(r.size.w)cast<int>(r.size.h)));
158             SetAutoSized();
159         }
160         private inline nothrow void SetAutoSizeFlag()
161         {
162             flags = cast<Flags>(flags | Flags.autoSize);
163         }
164         private inline nothrow void ResetAutoSizeFlag()
165         {
166             flags = cast<Flags>(flags & ~Flags.autoSize);
167         }
168         private inline nothrow bool AutoSized() const
169         {
170             return (flags & Flags.autoSized) != Flags.none;
171         }
172         private inline nothrow void SetAutoSized()
173         {
174             flags = cast<Flags>(flags | Flags.autoSized);
175         }
176         private inline nothrow void ResetAutoSized()
177         {
178             flags = cast<Flags>(flags & ~Flags.autoSized);
179         }
180         private Flags flags;
181     }
182 }