makepad_widgets/
view_ui.rs

1use {
2    crate::makepad_platform::*
3};
4
5live_design! {
6    link widgets;
7    
8    use link::theme::*;
9    use crate::view::ViewBase;
10    use crate::scroll_bars::ScrollBars;
11    use makepad_draw::shader::std::*;
12    
13    pub View = <ViewBase> {}
14    
15    pub Hr = <View> {
16        width: Fill, height: (THEME_SPACE_2 * 7.5),
17        flow: Down,
18        margin: 0.
19
20        show_bg: true, 
21        draw_bg: {
22            uniform color_1: (THEME_COLOR_BEVEL_OUTSET_2)
23            uniform color_2: (THEME_COLOR_BEVEL_OUTSET_1)
24            uniform border_size: (THEME_BEVELING)
25
26            fn pixel(self) -> vec4 {
27                let sdf = Sdf2d::viewport(self.pos * self.rect_size)
28                let sz = self.border_size * 2.
29
30                sdf.rect(
31                    0.,
32                    self.rect_size.y * 0.5 - sz * 2,
33                    self.rect_size.x,
34                    sz + 1
35                )
36
37                sdf.fill(self.color_1);
38
39                sdf.rect(
40                    0,
41                    self.rect_size.y * 0.5 - sz,
42                    self.rect_size.x,
43                    sz 
44                )
45
46                sdf.fill(self.color_2);
47                return sdf.result
48            }
49        }
50    }
51    
52    pub Vr = <View> {
53        width: (THEME_SPACE_2 * 2.), height: Fill,
54        flow: Right,
55
56        show_bg: true, 
57        draw_bg: {
58            uniform color_1: (THEME_COLOR_BEVEL_OUTSET_2)
59            uniform color_2: (THEME_COLOR_BEVEL_OUTSET_1)
60            uniform border_size: (THEME_BEVELING)
61
62            fn pixel(self) -> vec4 {
63                let sdf = Sdf2d::viewport(self.pos * self.rect_size)
64                let sz = self.border_size * 2.
65
66                sdf.rect(
67                    self.rect_size.x * 0.5,
68                    0.,
69                    sz + 1.,
70                    self.rect_size.y
71                )
72
73                sdf.fill(self.color_1);
74
75                sdf.rect(
76                    self.rect_size.x * 0.5 + sz,
77                    0.,
78                    sz,
79                    self.rect_size.y
80                )
81
82                sdf.fill(self.color_2);
83
84                return sdf.result
85            }
86        }
87    }
88    
89    // Spacer = <View> { width: Fill, height: Fill }
90    pub Filler = <View> { width: Fill, height: Fill }
91    
92    pub SolidView = <ViewBase> {
93        show_bg: true, 
94        draw_bg: {
95            fn get_color(self) -> vec4 {
96                return self.color
97            }
98                    
99            fn pixel(self) -> vec4 {
100                return Pal::premul(self.get_color())
101            }
102        }
103    }
104    /*
105    Debug = <View> {show_bg: true, draw_bg: {
106        color: #f00
107        fn pixel(self) -> vec4 {
108            return self.color
109        }
110    }}*/
111        
112    pub RectView = <ViewBase> {
113        show_bg: true, 
114        draw_bg: {
115            uniform border_size: 0.0
116            uniform border_color: #0000
117            uniform border_inset: vec4(0.0, 0.0, 0.0, 0.0)
118                        
119            fn get_color(self) -> vec4 {
120                return self.color
121            }
122                        
123            fn get_border_color(self) -> vec4 {
124                return self.border_color
125            }
126                        
127            fn pixel(self) -> vec4 {
128                let sdf = Sdf2d::viewport(self.pos * self.rect_size);
129                sdf.rect(
130                    self.border_inset.x + self.border_size,
131                    self.border_inset.y + self.border_size,
132                    self.rect_size.x - (self.border_inset.x + self.border_inset.z + self.border_size * 2.0),
133                    self.rect_size.y - (self.border_inset.y + self.border_inset.w + self.border_size * 2.0)
134                )
135                sdf.fill_keep(self.get_color())
136                if self.border_size > 0.0 {
137                    sdf.stroke(self.get_border_color(), self.border_size)
138                }
139                return sdf.result
140            }
141        }
142    }
143        
144    pub RectShadowView = <ViewBase> {
145        clip_x:false,
146        clip_y:false,
147                
148        show_bg: true, 
149        draw_bg: {
150            uniform border_size: 0.0
151            uniform border_color: #0000
152            uniform shadow_color: #0007
153            uniform shadow_offset: vec2(0.0,0.0)
154            uniform shadow_radius: 10.0
155                    
156            varying rect_size2: vec2,
157            varying rect_size3: vec2,
158            varying sdf_rect_pos: vec2,
159            varying sdf_rect_size: vec2,
160            varying rect_pos2: vec2,     
161            varying rect_shift: vec2,  
162
163            fn get_color(self) -> vec4 {
164                return self.color
165            }
166                    
167            fn vertex(self) -> vec4 {
168                let min_offset = min(self.shadow_offset,vec2(0));
169                self.rect_size2 = self.rect_size + 2.0*vec2(self.shadow_radius);
170                self.rect_size3 = self.rect_size2 + abs(self.shadow_offset);
171                self.rect_pos2 = self.rect_pos - vec2(self.shadow_radius) + min_offset;
172                self.rect_shift = -min_offset;
173                self.sdf_rect_size = self.rect_size2 - vec2(self.shadow_radius * 2.0 + self.border_size * 2.0)
174                self.sdf_rect_pos = -min_offset + vec2(self.border_size + self.shadow_radius);
175                return self.clip_and_transform_vertex(self.rect_pos2, self.rect_size3)
176            }
177                                                
178            fn get_border_color(self) -> vec4 {
179                return self.border_color
180            }
181                                        
182            fn pixel(self) -> vec4 {
183                            
184                let sdf = Sdf2d::viewport(self.pos * self.rect_size3)
185                sdf.rect(
186                    self.sdf_rect_pos.x,
187                    self.sdf_rect_pos.y,
188                    self.sdf_rect_size.x,
189                    self.sdf_rect_size.y 
190                )
191                if sdf.shape > -1.0{ // try to skip the expensive gauss shadow
192                    let m = self.shadow_radius;
193                    let o = self.shadow_offset + self.rect_shift;
194                    let v = GaussShadow::box_shadow(vec2(m) + o, self.rect_size2+o, self.pos * (self.rect_size3+vec2(m)) , m*0.5);
195                    sdf.clear(self.shadow_color*v)
196                }
197                                                                
198                sdf.fill_keep(self.get_color())
199                if self.border_size > 0.0 {
200                    sdf.stroke(self.get_border_color(), self.border_size)
201                }
202                return sdf.result
203            }
204        }
205    }
206                
207    pub RoundedShadowView = <ViewBase>{
208        clip_x:false,
209        clip_y:false,
210                            
211        show_bg: true,
212        draw_bg: {
213            color: #8
214            uniform border_radius: 2.5
215            uniform border_size: 0.0
216            uniform border_color: #0000
217            uniform shadow_color: #0007
218            uniform shadow_radius: 20.0,
219            uniform shadow_offset: vec2(0.0,0.0)
220                                            
221            varying rect_size2: vec2,
222            varying rect_size3: vec2,
223            varying rect_pos2: vec2,     
224            varying rect_shift: vec2,    
225            varying sdf_rect_pos: vec2,
226            varying sdf_rect_size: vec2,
227                                              
228            fn get_color(self) -> vec4 {
229                return self.color
230            }
231                                            
232            fn vertex(self) -> vec4 {
233                let min_offset = min(self.shadow_offset,vec2(0));
234                self.rect_size2 = self.rect_size + 2.0*vec2(self.shadow_radius);
235                self.rect_size3 = self.rect_size2 + abs(self.shadow_offset);
236                self.rect_pos2 = self.rect_pos - vec2(self.shadow_radius) + min_offset;
237                self.sdf_rect_size = self.rect_size2 - vec2(self.shadow_radius * 2.0 + self.border_size * 2.0)
238                self.sdf_rect_pos = -min_offset + vec2(self.border_size + self.shadow_radius);
239                self.rect_shift = -min_offset;
240                                                            
241                return self.clip_and_transform_vertex(self.rect_pos2, self.rect_size3)
242            }
243                                                        
244            fn get_border_color(self) -> vec4 {
245                return self.border_color
246            }
247                                                
248            fn pixel(self) -> vec4 {
249                                                                
250                let sdf = Sdf2d::viewport(self.pos * self.rect_size3)
251                sdf.box(
252                    self.sdf_rect_pos.x,
253                    self.sdf_rect_pos.y,
254                    self.sdf_rect_size.x,
255                    self.sdf_rect_size.y, 
256                    max(1.0, self.border_radius)
257                )
258                if sdf.shape > -1.0{ // try to skip the expensive gauss shadow
259                    let m = self.shadow_radius;
260                    let o = self.shadow_offset + self.rect_shift;
261                    let v = GaussShadow::rounded_box_shadow(vec2(m) + o, self.rect_size2+o, self.pos * (self.rect_size3+vec2(m)), self.shadow_radius*0.5, self.border_radius*2.0);
262                    sdf.clear(self.shadow_color*v)
263                }
264                                                                    
265                sdf.fill_keep(self.get_color())
266                if self.border_size > 0.0 {
267                    sdf.stroke(self.get_border_color(), self.border_size)
268                }
269                return sdf.result
270            }
271        }
272    }
273                
274    pub RoundedView = <ViewBase> {
275        show_bg: true, 
276        draw_bg: {
277            uniform border_size: 0.0
278            uniform border_radius: 2.5
279            uniform border_color: #0000
280            uniform border_inset: vec4(0.0, 0.0, 0.0, 0.0)
281                                
282            fn get_color(self) -> vec4 {
283                return self.color
284            }
285                                
286            fn get_border_color(self) -> vec4 {
287                return self.border_color
288            }
289                                
290            fn pixel(self) -> vec4 {
291                let sdf = Sdf2d::viewport(self.pos * self.rect_size)
292                sdf.box(
293                    self.border_inset.x + self.border_size,
294                    self.border_inset.y + self.border_size,
295                    self.rect_size.x - (self.border_inset.x + self.border_inset.z + self.border_size * 2.0),
296                    self.rect_size.y - (self.border_inset.y + self.border_inset.w + self.border_size * 2.0),
297                    max(1.0, self.border_radius)
298                )
299                sdf.fill_keep(self.get_color())
300                if self.border_size > 0.0 {
301                    sdf.stroke(self.get_border_color(), self.border_size)
302                }
303                return sdf.result;
304            }
305        }
306    }
307                
308    pub RoundedXView = <ViewBase> {
309        show_bg: true, 
310        draw_bg: {
311            uniform border_size: 0.0
312            uniform border_color: #0000
313            uniform border_inset: vec4(0.0, 0.0, 0.0, 0.0)
314            uniform border_radius: vec2(2.5, 2.5)
315                            
316            fn get_color(self) -> vec4 {
317                return self.color
318            }
319                            
320            fn get_border_color(self) -> vec4 {
321                return self.border_color
322            }
323                            
324            fn pixel(self) -> vec4 {
325                let sdf = Sdf2d::viewport(self.pos * self.rect_size)
326                sdf.box_x(
327                    self.border_inset.x + self.border_size,
328                    self.border_inset.y + self.border_size,
329                    self.rect_size.x - (self.border_inset.x + self.border_inset.z + self.border_size * 2.0),
330                    self.rect_size.y - (self.border_inset.y + self.border_inset.w + self.border_size * 2.0),
331                    self.border_radius.x,
332                    self.border_radius.y
333                )
334                sdf.fill_keep(self.get_color())
335                if self.border_size > 0.0 {
336                    sdf.stroke(self.get_border_color(), self.border_size)
337                }
338                return sdf.result;
339            }
340        }
341    }
342                
343    pub RoundedYView = <ViewBase> {
344        show_bg: true, 
345        draw_bg: {
346            uniform border_size: 0.0
347            uniform border_color: #0000
348            uniform border_inset: vec4(0.0, 0.0, 0.0, 0.0)
349            uniform border_radius: vec2(2.5, 2.5)
350                            
351            fn get_color(self) -> vec4 {
352                return self.color
353            }
354                            
355            fn get_border_color(self) -> vec4 {
356                return self.border_color
357            }
358                            
359            fn pixel(self) -> vec4 {
360                let sdf = Sdf2d::viewport(self.pos * self.rect_size)
361                sdf.box_y(
362                    self.border_inset.x + self.border_size,
363                    self.border_inset.y + self.border_size,
364                    self.rect_size.x - (self.border_inset.x + self.border_inset.z + self.border_size * 2.0),
365                    self.rect_size.y - (self.border_inset.y + self.border_inset.w + self.border_size * 2.0),
366                    self.border_radius.x,
367                    self.border_radius.y
368                )
369                sdf.fill_keep(self.get_color())
370                if self.border_size > 0.0 {
371                    sdf.stroke(self.get_border_color(), self.border_size)
372                }
373                return sdf.result;
374            }
375        }
376    }
377                
378    pub RoundedAllView = <ViewBase> {
379        show_bg: true, 
380        draw_bg: {
381            uniform border_size: 0.0
382            uniform border_color: #0000
383            uniform border_inset: vec4(0.0, 0.0, 0.0, 0.0)
384            uniform border_radius: vec4(2.5, 2.5, 2.5, 2.5)
385                            
386            fn get_color(self) -> vec4 {
387                return self.color
388            }
389                            
390            fn get_border_color(self) -> vec4 {
391                return self.border_color
392            }
393                            
394            fn pixel(self) -> vec4 {
395                let sdf = Sdf2d::viewport(self.pos * self.rect_size)
396                sdf.box_all(
397                    self.border_inset.x + self.border_size,
398                    self.border_inset.y + self.border_size,
399                    self.rect_size.x - (self.border_inset.x + self.border_inset.z + self.border_size * 2.0),
400                    self.rect_size.y - (self.border_inset.y + self.border_inset.w + self.border_size * 2.0),
401                    self.border_radius.x,
402                    self.border_radius.y,
403                    self.border_radius.z,
404                    self.border_radius.w
405                )
406                sdf.fill_keep(self.get_color())
407                if self.border_size > 0.0 {
408                    sdf.stroke(self.get_border_color(), self.border_size)
409                }
410                return sdf.result;
411            }
412        }
413    }
414                
415    pub CircleView = <ViewBase> {
416        show_bg: true, 
417        draw_bg: {
418            uniform border_size: 0.0
419            uniform border_color: #0000
420            uniform border_inset: vec4(0.0, 0.0, 0.0, 0.0)
421            uniform border_radius: 5.0
422                            
423            fn get_color(self) -> vec4 {
424                return self.color
425            }
426                            
427            fn get_border_color(self) -> vec4 {
428                return self.border_color
429            }
430                            
431            fn pixel(self) -> vec4 {
432                let sdf = Sdf2d::viewport(self.pos * self.rect_size)
433                if self.border_radius > 0.0 {
434                    sdf.circle(
435                        self.rect_size.x * 0.5,
436                        self.rect_size.y * 0.5,
437                        self.border_radius
438                    )
439                }
440                else {
441                    sdf.circle(
442                        self.rect_size.x * 0.5,
443                        self.rect_size.y * 0.5,
444                        min(
445                            (self.rect_size.x - (self.border_inset.x + self.border_inset.z + 2.0 * self.border_size)) * 0.5,
446                            (self.rect_size.y - (self.border_inset.y + self.border_inset.w + 2.0 * self.border_size)) * 0.5
447                        )
448                    )
449                }
450                sdf.fill_keep(self.get_color())
451                if self.border_size > 0.0 {
452                    sdf.stroke(self.get_border_color(), self.border_size)
453                }
454                return sdf.result
455            }
456        }
457    }
458                
459    pub HexagonView = <ViewBase> {
460        show_bg: true, 
461        draw_bg: {
462            uniform border_size: 0.0
463            uniform border_color: #0000
464            uniform border_inset: vec4(0.0, 0.0, 0.0, 0.0)
465            uniform border_radius: vec2(0.0, 1.0)
466                            
467            fn get_color(self) -> vec4 {
468                return self.color
469            }
470                            
471            fn get_border_color(self) -> vec4 {
472                return self.border_color
473            }
474                            
475            fn pixel(self) -> vec4 {
476                let sdf = Sdf2d::viewport(self.pos * self.rect_size)
477                if self.border_radius.x > 0.0 {
478                    sdf.hexagon(
479                        self.rect_size.x * 0.5,
480                        self.rect_size.y * 0.5,
481                        self.border_radius.x
482                    )
483                }
484                else {
485                    sdf.hexagon(
486                        self.rect_size.x * 0.5,
487                        self.rect_size.y * 0.5,
488                        min(
489                            (self.rect_size.x - (self.border_inset.x + self.border_inset.z + 2.0 * self.border_size)) * 0.5,
490                            (self.rect_size.y - (self.border_inset.y + self.border_inset.w + 2.0 * self.border_size)) * 0.5
491                        )
492                    )
493                }
494                sdf.fill_keep(self.color)
495                if self.border_size > 0.0 {
496                    sdf.stroke(self.border_color, self.border_size)
497                }
498                return sdf.result
499            }
500        }
501    }
502                
503    pub GradientXView = <ViewBase> {
504        show_bg: true, 
505        draw_bg: {
506            uniform color_1: #00f
507            uniform color_2: #f00
508            uniform color_dither: 1.0
509
510            fn get_color(self) -> vec4 {
511                
512                let dither = Math::random_2d(self.pos.xy) * 0.04 * self.color_dither;
513                return mix(self.color_1, self.color_2, self.pos.x + dither)
514            }
515                            
516            fn pixel(self) -> vec4 {
517                return Pal::premul(self.get_color())
518            }
519        }
520    }
521                
522    pub GradientYView = <ViewBase> {
523        show_bg: true, 
524        draw_bg: {
525            uniform color_1: #00f
526            uniform color_2: #f00
527            uniform color_dither: 1.0
528
529            fn get_color(self) -> vec4 {
530                let dither = Math::random_2d(self.pos.xy) * 0.04 * self.color_dither;
531                return mix(self.color_1, self.color_2, self.pos.y + dither)
532            }
533                            
534            fn pixel(self) -> vec4 {
535                return Pal::premul(self.get_color())
536            }
537        }
538    }
539                
540    pub CachedView = <ViewBase> {
541        optimize: Texture,
542        draw_bg: {
543            texture image: texture2d
544            varying scale: vec2
545            varying shift: vec2
546            fn vertex(self) -> vec4 {
547                let dpi = self.dpi_factor;
548                let ceil_size = ceil(self.rect_size * dpi) / dpi
549                let floor_pos = floor(self.rect_pos * dpi) / dpi
550                self.scale = self.rect_size / ceil_size;
551                self.shift = (self.rect_pos - floor_pos) / ceil_size;
552                return self.clip_and_transform_vertex(self.rect_pos, self.rect_size)
553            }
554            fn pixel(self) -> vec4 {
555                return sample2d_rt(self.image, self.pos * self.scale + self.shift);// + mix(#f00,#0f0,self.pos.y);
556            }
557        }
558    }
559            
560    pub CachedRoundedView = <ViewBase> {
561        optimize: Texture,
562        draw_bg: {
563            uniform border_size: 0.0
564            uniform border_color: #000F
565            uniform border_inset: vec4(0., 0., 0., 0.)
566            uniform border_radius: 2.5
567                                
568            texture image: texture2d
569            varying scale: vec2
570            varying shift: vec2
571                                            
572            fn get_border_color(self) -> vec4 {
573                return self.border_color
574            }
575                                        
576            fn vertex(self) -> vec4 {
577                let dpi = self.dpi_factor;
578                let ceil_size = ceil(self.rect_size * dpi) / dpi
579                let floor_pos = floor(self.rect_pos * dpi) / dpi
580                self.scale = self.rect_size / ceil_size;
581                self.shift = (self.rect_pos - floor_pos) / ceil_size;
582                return self.clip_and_transform_vertex(self.rect_pos, self.rect_size)
583            }
584                                
585            fn pixel(self) -> vec4 {
586                                        
587                let sdf = Sdf2d::viewport(self.pos * self.rect_size)
588                sdf.box(
589                    self.border_inset.x + self.border_size,
590                    self.border_inset.y + self.border_size,
591                    self.rect_size.x - (self.border_inset.x + self.border_inset.z + self.border_size * 2.0),
592                    self.rect_size.y - (self.border_inset.y + self.border_inset.w + self.border_size * 2.0),
593                    max(1.0, self.border_radius)
594                )
595                let color = sample2d_rt(self.image, self.pos * self.scale + self.shift);
596                sdf.fill_keep_premul(color);
597                if self.border_size > 0.0 {
598                    sdf.stroke(self.get_border_color(), self.border_size)
599                }
600                return sdf.result;
601            }
602        }
603    }
604    
605    pub CachedScrollXY = <CachedView> {
606        scroll_bars: <ScrollBars> {show_scroll_x: true, show_scroll_y: true}
607    }
608        
609    pub CachedScrollX = <CachedView> {
610        scroll_bars: <ScrollBars> {show_scroll_x: true, show_scroll_y: false}
611    }
612        
613    pub CachedScrollY = <CachedView> {
614        scroll_bars: <ScrollBars> {show_scroll_x: false, show_scroll_y: true}
615    }
616        
617    pub ScrollXYView = <ViewBase> {scroll_bars: <ScrollBars> {show_scroll_x: true, show_scroll_y: true}}
618    pub ScrollXView = <ViewBase> {scroll_bars: <ScrollBars> {show_scroll_x: true, show_scroll_y: false}}
619    pub ScrollYView = <ViewBase> {scroll_bars: <ScrollBars> {show_scroll_x: false, show_scroll_y: true}}
620}