~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/xwt/Xwt/Xwt/ColorSelector.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// 
 
2
// ColorSelector.cs
 
3
//  
 
4
// Author:
 
5
//       Lluis Sanchez <lluis@xamarin.com>
 
6
// 
 
7
// Copyright (c) 2012 Xamarin Inc
 
8
// 
 
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
 
10
// of this software and associated documentation files (the "Software"), to deal
 
11
// in the Software without restriction, including without limitation the rights
 
12
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
13
// copies of the Software, and to permit persons to whom the Software is
 
14
// furnished to do so, subject to the following conditions:
 
15
// 
 
16
// The above copyright notice and this permission notice shall be included in
 
17
// all copies or substantial portions of the Software.
 
18
// 
 
19
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
20
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
21
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
22
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
23
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
24
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
25
// THE SOFTWARE.
 
26
using System;
 
27
using Xwt.Drawing;
 
28
using Xwt.Backends;
 
29
using System.Collections.Generic;
 
30
 
 
31
 
 
32
namespace Xwt
 
33
{
 
34
        public class ColorSelector: Widget
 
35
        {
 
36
                protected new class WidgetBackendHost: Widget.WidgetBackendHost, IColorSelectorEventSink
 
37
                {
 
38
                        protected override IBackend OnCreateBackend ()
 
39
                        {
 
40
                                var b = base.OnCreateBackend ();
 
41
                                if (b is ICustomWidgetBackend)
 
42
                                        b = new DefaultColorSelectorBackend ();
 
43
                                return b;
 
44
                        }
 
45
                        
 
46
                        public void OnColorChanged ()
 
47
                        {
 
48
                                ((ColorSelector)Parent).OnColorChanged (EventArgs.Empty);
 
49
                        }
 
50
                }
 
51
                
 
52
                public ColorSelector ()
 
53
                {
 
54
                }
 
55
                
 
56
                protected override Xwt.Backends.BackendHost CreateBackendHost ()
 
57
                {
 
58
                        return new WidgetBackendHost ();
 
59
                }
 
60
 
 
61
                IColorSelectorBackend Backend {
 
62
                        get { return (IColorSelectorBackend) BackendHost.Backend; }
 
63
                }
 
64
                
 
65
                /// <summary>
 
66
                /// Gets or sets the selected color
 
67
                /// </summary>
 
68
                public Color Color {
 
69
                        get { return Backend.Color; }
 
70
                        set { Backend.Color = value; }
 
71
                }
 
72
                
 
73
                public bool SupportsAlpha {
 
74
                        get { return Backend.SupportsAlpha; }
 
75
                        set { Backend.SupportsAlpha = value; }
 
76
                }
 
77
                
 
78
                protected virtual void OnColorChanged (EventArgs args)
 
79
                {
 
80
                        if (colorChanged != null)
 
81
                                colorChanged (this, args);
 
82
                }
 
83
                
 
84
                EventHandler colorChanged;
 
85
                
 
86
                public event EventHandler ColorChanged {
 
87
                        add {
 
88
                                BackendHost.OnBeforeEventAdd (ColorSelectorEvent.ColorChanged, colorChanged);
 
89
                                colorChanged += value;
 
90
                        }
 
91
                        remove {
 
92
                                colorChanged -= value;
 
93
                                BackendHost.OnAfterEventRemove (ColorSelectorEvent.ColorChanged, colorChanged);
 
94
                        }
 
95
                }
 
96
        }
 
97
        
 
98
        class DefaultColorSelectorBackend: XwtWidgetBackend, IColorSelectorBackend
 
99
        {
 
100
                HueBox hsBox;
 
101
                LightBox lightBox;
 
102
                ColorSelectionBox colorBox;
 
103
                TextEntry hueEntry;
 
104
                TextEntry satEntry;
 
105
                TextEntry lightEntry;
 
106
                TextEntry redEntry;
 
107
                TextEntry greenEntry;
 
108
                TextEntry blueEntry;
 
109
                TextEntry alphaEntry;
 
110
                HSeparator alphaSeparator;
 
111
                Color currentColor;
 
112
                bool loadingEntries;
 
113
                List<Widget> alphaControls = new List<Widget> ();
 
114
                
 
115
                public DefaultColorSelectorBackend ()
 
116
                {
 
117
                        HBox box = new HBox ();
 
118
                        Table selBox = new Table ();
 
119
                        hsBox = new HueBox ();
 
120
                        hsBox.Light = 0.5;
 
121
                        lightBox = new LightBox ();
 
122
                        hsBox.SelectionChanged += delegate {
 
123
                                lightBox.Hue = hsBox.SelectedColor.Hue;
 
124
                                lightBox.Saturation = hsBox.SelectedColor.Saturation;
 
125
                        };
 
126
                        
 
127
                        colorBox = new ColorSelectionBox () { MinHeight = 20 };
 
128
                        
 
129
                        selBox.Attach (hsBox, 0, 0);
 
130
                        selBox.Attach (lightBox, 1, 0);
 
131
                        
 
132
                        box.PackStart (selBox);
 
133
                        
 
134
                        int entryWidth = 40;
 
135
                        VBox entryBox = new VBox ();
 
136
                        Table entryTable = new Table ();
 
137
                        
 
138
                        entryTable.Attach (new Label ("Color:"), 0, 0);
 
139
                        entryTable.Attach (colorBox, 1, 5, 0, 1);
 
140
                        entryTable.Attach (new HSeparator (), 0, 5, 1, 2);
 
141
                        
 
142
                        int r = 2;
 
143
                        entryTable.Attach (new Label ("Hue:"), 0, r);
 
144
                        entryTable.Attach (hueEntry = new TextEntry () { MinWidth = entryWidth }, 1, r++);
 
145
                        
 
146
                        entryTable.Attach (new Label ("Saturation:"), 0, r);
 
147
                        entryTable.Attach (satEntry = new TextEntry () { MinWidth = entryWidth }, 1, r++);
 
148
                        
 
149
                        entryTable.Attach (new Label ("Light:"), 0, r);
 
150
                        entryTable.Attach (lightEntry = new TextEntry () { MinWidth = entryWidth }, 1, r++);
 
151
                        
 
152
                        r = 2;
 
153
                        entryTable.Attach (new Label ("Red:"), 3, r);
 
154
                        entryTable.Attach (redEntry = new TextEntry () { MinWidth = entryWidth }, 4, r++);
 
155
                        
 
156
                        entryTable.Attach (new Label ("Green:"), 3, r);
 
157
                        entryTable.Attach (greenEntry = new TextEntry () { MinWidth = entryWidth }, 4, r++);
 
158
                        
 
159
                        entryTable.Attach (new Label ("Blue:"), 3, r);
 
160
                        entryTable.Attach (blueEntry = new TextEntry () { MinWidth = entryWidth }, 4, r++);
 
161
                        
 
162
                        Label label;
 
163
                        entryTable.Attach (alphaSeparator = new HSeparator (), 0, 5, r, ++r);
 
164
                        entryTable.Attach (label = new Label ("Opacity:"), 0, r);
 
165
                        entryTable.Attach (alphaEntry = new TextEntry () { MinWidth = entryWidth }, 1, r);
 
166
                        
 
167
                        alphaControls.Add (alphaSeparator);
 
168
                        alphaControls.Add (label);
 
169
                        alphaControls.Add (alphaEntry);
 
170
                        
 
171
                        entryBox.PackStart (entryTable);
 
172
                        box.PackStart (entryBox);
 
173
                        Content = box;
 
174
                        
 
175
                        hsBox.SelectionChanged += delegate {
 
176
                                HandleColorBoxSelectionChanged ();
 
177
                        };
 
178
                        lightBox.SelectionChanged += delegate {
 
179
                                HandleColorBoxSelectionChanged ();
 
180
                        };
 
181
                        
 
182
                        hueEntry.Changed += HandleHslChanged;
 
183
                        satEntry.Changed += HandleHslChanged;
 
184
                        lightEntry.Changed += HandleHslChanged;
 
185
                        redEntry.Changed += HandleRgbChanged;
 
186
                        greenEntry.Changed += HandleRgbChanged;
 
187
                        blueEntry.Changed += HandleRgbChanged;
 
188
                        alphaEntry.Changed += HandleAlphaChanged;
 
189
                        
 
190
                        Color = Colors.White;
 
191
                }
 
192
 
 
193
                void HandleAlphaChanged (object sender, EventArgs e)
 
194
                {
 
195
                        if (loadingEntries)
 
196
                                return;
 
197
                        
 
198
                        int a;
 
199
                        if (!int.TryParse (alphaEntry.Text, out a))
 
200
                                return;
 
201
                        
 
202
                        currentColor = currentColor.WithAlpha ((double)a / 255d);
 
203
                        LoadColorBoxSelection ();
 
204
                }
 
205
 
 
206
                void HandleHslChanged (object sender, EventArgs e)
 
207
                {
 
208
                        if (loadingEntries)
 
209
                                return;
 
210
                        
 
211
                        int h, s, l;
 
212
                        if (!int.TryParse (hueEntry.Text, out h))
 
213
                                return;
 
214
                        if (!int.TryParse (satEntry.Text, out s))
 
215
                                return;
 
216
                        if (!int.TryParse (lightEntry.Text, out l))
 
217
                                return;
 
218
                        
 
219
                        currentColor = Color.FromHsl ((double)h / 255d, (double)s / 255d, (double)l / 255d, currentColor.Alpha);
 
220
                        LoadColorBoxSelection ();
 
221
                        LoadRgbEntries ();
 
222
                }
 
223
 
 
224
                void HandleRgbChanged (object sender, EventArgs e)
 
225
                {
 
226
                        if (loadingEntries)
 
227
                                return;
 
228
                        
 
229
                        int r, g, b;
 
230
                        if (!int.TryParse (redEntry.Text, out r))
 
231
                                return;
 
232
                        if (!int.TryParse (greenEntry.Text, out g))
 
233
                                return;
 
234
                        if (!int.TryParse (blueEntry.Text, out b))
 
235
                                return;
 
236
                        
 
237
                        currentColor = new Color ((double)r / 255d, (double)g / 255d, (double)b / 255d, currentColor.Alpha);
 
238
                        LoadColorBoxSelection ();
 
239
                        LoadHslEntries ();
 
240
                }
 
241
 
 
242
                void HandleColorBoxSelectionChanged ()
 
243
                {
 
244
                        currentColor = Color.FromHsl (
 
245
                                hsBox.SelectedColor.Hue,
 
246
                                hsBox.SelectedColor.Saturation,
 
247
                                lightBox.Light,
 
248
                                currentColor.Alpha);
 
249
                        
 
250
                        colorBox.Color = currentColor;
 
251
                        LoadHslEntries ();
 
252
                        LoadRgbEntries ();
 
253
                }
 
254
                
 
255
                void LoadAlphaEntry ()
 
256
                {
 
257
                        alphaEntry.Text = ((int)(currentColor.Alpha * 255)).ToString ();
 
258
                }
 
259
                
 
260
                void LoadHslEntries ()
 
261
                {
 
262
                        loadingEntries = true;
 
263
                        hueEntry.Text = ((int)(currentColor.Hue * 255)).ToString ();
 
264
                        satEntry.Text = ((int)(currentColor.Saturation * 255)).ToString ();
 
265
                        lightEntry.Text = ((int)(currentColor.Light * 255)).ToString ();
 
266
                        loadingEntries = false;
 
267
                }
 
268
 
 
269
                void LoadRgbEntries ()
 
270
                {
 
271
                        loadingEntries = true;
 
272
                        redEntry.Text = ((int)(currentColor.Red * 255)).ToString ();
 
273
                        greenEntry.Text = ((int)(currentColor.Green * 255)).ToString ();
 
274
                        blueEntry.Text = ((int)(currentColor.Blue * 255)).ToString ();
 
275
                        loadingEntries = false;
 
276
                }
 
277
                
 
278
                void LoadColorBoxSelection ()
 
279
                {
 
280
                        hsBox.SelectedColor = currentColor;
 
281
                        lightBox.Light = currentColor.Light;
 
282
                        lightBox.Hue = hsBox.SelectedColor.Hue;
 
283
                        lightBox.Saturation = hsBox.SelectedColor.Saturation;
 
284
                        colorBox.Color = currentColor;
 
285
                }
 
286
                
 
287
                #region IColorSelectorBackend implementation
 
288
                public Color Color {
 
289
                        get {
 
290
                                return currentColor;
 
291
                        }
 
292
                        set {
 
293
                                currentColor = value;
 
294
                                LoadColorBoxSelection ();
 
295
                                LoadRgbEntries ();
 
296
                                LoadHslEntries ();
 
297
                                LoadAlphaEntry ();
 
298
                        }
 
299
                }
 
300
 
 
301
                public bool SupportsAlpha {
 
302
                        get {
 
303
                                return alphaControls [0].Visible;
 
304
                        }
 
305
                        set {
 
306
                                foreach (var w in alphaControls)
 
307
                                        w.Visible = value;
 
308
                        }
 
309
                }
 
310
                #endregion
 
311
        }
 
312
        
 
313
        class HueBox: Canvas
 
314
        {
 
315
                const int size = 150;
 
316
                const int padding = 3;
 
317
                bool buttonDown;
 
318
                Point selection;
 
319
                Image colorBox;
 
320
                double light;
 
321
                
 
322
                public double Light {
 
323
                        get {
 
324
                                return light;
 
325
                        }
 
326
                        set {
 
327
                                light = value;
 
328
                                if (colorBox != null) {
 
329
                                        colorBox.Dispose ();
 
330
                                        colorBox = null;
 
331
                                }
 
332
                                QueueDraw ();
 
333
                        }
 
334
                }
 
335
                
 
336
                public Color SelectedColor {
 
337
                        get { return GetColor ((int)selection.X, (int)selection.Y); }
 
338
                        set {
 
339
                                selection.X = (size - 1) * value.Hue;
 
340
                                selection.Y = (size - 1) * (1 - value.Saturation);
 
341
                                QueueDraw ();
 
342
                        }
 
343
                }
 
344
                
 
345
                public HueBox ()
 
346
                {
 
347
                        MinWidth = size + padding * 2;
 
348
                        MinHeight = size + padding * 2;
 
349
                }
 
350
                
 
351
                protected override void OnDraw (Context ctx, Rectangle dirtyRect)
 
352
                {
 
353
                        if (colorBox == null) {
 
354
                                ImageBuilder ib = new ImageBuilder (size, size);
 
355
                                for (int i=0; i<size; i++) {
 
356
                                        for (int j=0; j<size; j++) {
 
357
                                                ib.Context.Rectangle (i, j, 1, 1);
 
358
                                                ib.Context.SetColor (GetColor (i,j));
 
359
                                                ib.Context.Fill ();
 
360
                                        }
 
361
                                }
 
362
                                colorBox = ib.ToImage ();
 
363
                                ib.Dispose ();
 
364
                        }
 
365
                        ctx.DrawImage (colorBox, padding, padding);
 
366
                        ctx.SetLineWidth (1);
 
367
                        ctx.SetColor (Colors.Black);
 
368
                        ctx.Rectangle (selection.X + padding - 2 + 0.5, selection.Y + padding - 2 + 0.5, 4, 4);
 
369
                        ctx.Stroke ();
 
370
                }
 
371
                
 
372
                Color GetColor (int x, int y)
 
373
                {
 
374
                        return Color.FromHsl ((double)x / (double)(size-1), (double)(size - 1 - y) / (double)(size-1), Light);
 
375
                }
 
376
                
 
377
                protected override void OnButtonPressed (ButtonEventArgs args)
 
378
                {
 
379
                        base.OnButtonPressed (args);
 
380
                        buttonDown = true;
 
381
                        selection = new Point (args.X - padding, args.Y - padding);
 
382
                        OnSelectionChanged ();
 
383
                        QueueDraw ();
 
384
                }
 
385
                
 
386
                protected override void OnButtonReleased (ButtonEventArgs args)
 
387
                {
 
388
                        base.OnButtonReleased (args);
 
389
                        buttonDown = false;
 
390
                        QueueDraw ();
 
391
                }
 
392
                
 
393
                protected override void OnMouseMoved (MouseMovedEventArgs args)
 
394
                {
 
395
                        base.OnMouseMoved (args);
 
396
                        if (buttonDown) {
 
397
                                QueueDraw ();
 
398
                                selection = new Point (args.X - padding, args.Y - padding);
 
399
                                OnSelectionChanged ();
 
400
                        }
 
401
                }
 
402
                
 
403
                void OnSelectionChanged ()
 
404
                {
 
405
                        if (selection.X < 0)
 
406
                                selection.X = 0;
 
407
                        if (selection.Y < 0)
 
408
                                selection.Y = 0;
 
409
                        if (selection.X >= size)
 
410
                                selection.X = size - 1;
 
411
                        if (selection.Y >= size)
 
412
                                selection.Y = size - 1;
 
413
                        if (SelectionChanged != null)
 
414
                                SelectionChanged (this, EventArgs.Empty);
 
415
                }
 
416
                
 
417
                public event EventHandler SelectionChanged;
 
418
        }
 
419
        
 
420
        class LightBox: Canvas
 
421
        {
 
422
                const int padding = 3;
 
423
                double light;
 
424
                double saturation;
 
425
                double hue;
 
426
                bool buttonPressed;
 
427
 
 
428
                public double Hue {
 
429
                        get {
 
430
                                return hue;
 
431
                        }
 
432
                        set {
 
433
                                hue = value;
 
434
                                QueueDraw ();
 
435
                        }
 
436
                }
 
437
                
 
438
                public double Saturation {
 
439
                        get {
 
440
                                return saturation;
 
441
                        }
 
442
                        set {
 
443
                                saturation = value;
 
444
                                QueueDraw ();
 
445
                        }
 
446
                }
 
447
                
 
448
                public double Light {
 
449
                        get {
 
450
                                return light;
 
451
                        }
 
452
                        set {
 
453
                                light = value;
 
454
                                QueueDraw ();
 
455
                        }
 
456
                }       
 
457
                
 
458
                public LightBox ()
 
459
                {
 
460
                        MinWidth = 20;
 
461
                        MinHeight = 20;
 
462
                }
 
463
                
 
464
                protected override void OnDraw (Context ctx, Rectangle dirtyRect)
 
465
                {
 
466
                        double width = Size.Width - padding * 2;
 
467
                        int range = (int)Size.Height - padding * 2;
 
468
                        for (int n=0; n < range; n++) {
 
469
                                ctx.Rectangle (padding, padding + n, width, 1);
 
470
                                ctx.SetColor (Color.FromHsl (hue, saturation, (double)(range - n - 1) / (double)(range - 1)));
 
471
                                ctx.Fill ();
 
472
                        }
 
473
                        ctx.Rectangle (0.5, padding + (int)(((double)range) * (1-light)) + 0.5 - 2, Size.Width - 1, 4);
 
474
                        ctx.SetColor (Colors.Black);
 
475
                        ctx.SetLineWidth (1);
 
476
                        ctx.Stroke ();
 
477
                }
 
478
                
 
479
                protected override void OnButtonPressed (ButtonEventArgs args)
 
480
                {
 
481
                        base.OnButtonPressed (args);
 
482
                        buttonPressed = true;
 
483
                        OnSelectionChanged ((int)args.Y - padding);
 
484
                        QueueDraw ();
 
485
                }
 
486
                
 
487
                protected override void OnButtonReleased (ButtonEventArgs args)
 
488
                {
 
489
                        base.OnButtonReleased (args);
 
490
                        buttonPressed = false;
 
491
                        QueueDraw ();
 
492
                }
 
493
                
 
494
                protected override void OnMouseMoved (MouseMovedEventArgs args)
 
495
                {
 
496
                        base.OnMouseMoved (args);
 
497
                        if (buttonPressed) {
 
498
                                OnSelectionChanged ((int)args.Y - padding);
 
499
                                QueueDraw ();
 
500
                        }
 
501
                }
 
502
                
 
503
                void OnSelectionChanged (int y)
 
504
                {
 
505
                        int range = (int)Size.Height - padding * 2;
 
506
                        if (y < 0)
 
507
                                y = 0;
 
508
                        if (y >= range)
 
509
                                y = range - 1;
 
510
                        light = 1 - ((double) y / (double)(range - 1));
 
511
                        if (SelectionChanged != null)
 
512
                                SelectionChanged (this, EventArgs.Empty);
 
513
                }
 
514
                
 
515
                public event EventHandler SelectionChanged;
 
516
        }
 
517
        
 
518
        class ColorSelectionBox: Canvas
 
519
        {
 
520
                Color color;
 
521
                
 
522
                public Color Color {
 
523
                        get {
 
524
                                return color;
 
525
                        }
 
526
                        set {
 
527
                                color = value;
 
528
                                QueueDraw ();
 
529
                        }
 
530
                }
 
531
                
 
532
                protected override void OnDraw (Context ctx, Rectangle dirtyRect)
 
533
                {
 
534
                        ctx.Rectangle (Bounds);
 
535
                        ctx.SetColor (Colors.White);
 
536
                        ctx.Fill ();
 
537
                        
 
538
                        ctx.MoveTo (0, 0);
 
539
                        ctx.LineTo (Size.Width, 0);
 
540
                        ctx.LineTo (0, Size.Height);
 
541
                        ctx.LineTo (0, 0);
 
542
                        ctx.SetColor (Colors.Black);
 
543
                        ctx.Fill ();
 
544
                        
 
545
                        ctx.Rectangle (Bounds);
 
546
                        ctx.SetColor (color);
 
547
                        ctx.Fill ();
 
548
                }
 
549
        }
 
550
}
 
551