1 /*
2 * Copyright(c) 2016, OpenAV
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of the <organization> nor the
15 * names of its contributors may be used to endorse or promote
16 * products derived from this software without specific prior
17 * written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENAV BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "dialog.hxx"
33
34 #include "button.hxx"
35 #include "ui.hxx"
36 #include "theme.hxx"
37
38 #include <stdio.h>
39
40 using namespace Avtk;
41
Dialog(Avtk::UI * ui,int x_,int y_,int w_,int h_,std::string label_)42 Dialog::Dialog( Avtk::UI* ui, int x_, int y_, int w_, int h_, std::string label_) :
43 Group( ui, x_, y_, w_, h_, label_ )
44 {
45 mx = my = -1;
46
47 ok = new Button( ui, 0, 0, 60, 20, "OK" );
48 cancel = new Button( ui, 0, 0, 60, 20, "Cancel" );
49
50 add( ok );
51 add( cancel );
52
53 visible_ = false;
54
55 end();
56 }
57
draw(cairo_t * cr)58 void Dialog::draw( cairo_t* cr )
59 {
60 cairo_save( cr );
61
62 // buttons_
63 if( buttons_ == OK ) {
64 ok->x( x_ + w_ * 0.8 );
65 ok->y( y_ + h_ * 0.75 );
66 ok->visible( true );
67 } else if( buttons_ == OK_CANCEL ) {
68 ok->x( x_ + w_ * 0.8 - 70 );
69 ok->y( y_ + h_ * 0.75 );
70 cancel->x( x_ + w_ * 0.8 );
71 cancel->y( y_ + h_ * 0.75 );
72 ok->visible( true );
73 cancel->visible( true );
74 }
75
76 if( mx != -1 || my != -1 ) {
77 // get co-ords of the OK button, and find delta to mx/my
78 int xd = mx - (ok->x()+ok->w()/2.f);
79 int yd = my - (ok->y()+10);
80
81 // clip to *always* show entire dialog (aka, no "off-window" drawing)
82 int diagX = x_ + xd;
83 int diagY = y_ + yd;
84
85 // clip top left
86 if( diagX < 0 ) diagX = 0;
87 if( diagY < 0 ) diagY = 0;
88
89 // clip lower right
90 if( diagX + w_ > ui->w() ) diagX = ui->w() - w_;
91 if( diagY + h_ > ui->h() ) diagY = ui->h() - h_;
92
93 // set
94 x( diagX );
95 y( diagY );
96 }
97
98 // transparent-out the *entire* UI
99 cairo_rectangle( cr, 0, 0, ui->w(), ui->h() );
100 //theme_->color( cr, BG_DARK, 0.8 );
101 cairo_set_source_rgba( cr, 1, 1, 1, 0.2 );
102 cairo_fill_preserve( cr );
103 cairo_stroke( cr );
104
105 // draw diagonal lines
106 int end = ui->w() + ui->h();
107 for(int i = 0; i < end; i += 40 ) {
108 cairo_move_to( cr, -10, i + 10 );
109 cairo_line_to( cr, i + 10, -10 );
110 }
111 theme_->color( cr, BG_DARK, 0.2 );
112 //cairo_set_source_rgba( cr, 1, 1, 1, 0.2 );
113 cairo_set_line_width( cr, 13 );
114 cairo_stroke( cr );
115
116 // draw dark BG
117 cairo_rectangle( cr, x_+1, y_+1, w_-2, h_-1 );
118 theme_->color( cr, BG_DARK, 1 );
119 cairo_fill_preserve( cr );
120 cairo_set_line_width( cr, 1.0 );
121 cairo_stroke( cr );
122 theme_->color( cr, BG_DARK, 1 );
123 cairo_select_font_face(cr, "impact", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
124
125 // draw header
126 cairo_rectangle( cr, x_, y_, w_, 14 );
127 theme_->color( cr, HIGHLIGHT, 1.0 );
128 cairo_fill( cr );
129
130 /// TODO: get the dialog text amount, wrap based on text extents
131 /// and draw buttons in Y position to not interfere with text
132
133 // show the header
134 cairo_text_extents_t extents;
135 cairo_set_font_size(cr, 10.0);
136 cairo_text_extents(cr, label(), &extents);
137 cairo_move_to(cr, x_ + 4, y_ + 7 + (extents.height / 2) );
138 theme_->color( cr, BG_DARK, 1 );
139 cairo_show_text( cr, label() );
140
141 // show the content
142 cairo_set_font_size(cr, 12.0);
143 cairo_text_extents(cr, contents.c_str(), &extents);
144 cairo_move_to(cr, x_ + 4, y_ + 25 + 7 + (extents.height / 2) );
145 //theme_->color( cr, BG_DARK, 1 );
146 cairo_set_source_rgb( cr, 1,1,1 );
147 cairo_show_text( cr, contents.c_str() );
148
149
150 Group::draw( cr );
151
152 cairo_restore( cr );
153 }
154
155 // to highjack the OK / Cancel buttons events
valueCB(Avtk::Widget * widget)156 void Dialog::valueCB( Avtk::Widget* widget)
157 {
158 if( widget == ok ) {
159 ui->handleOnly( 0x0 );
160 visible( false );
161 value( 1.f );
162
163 callback( this, ui );
164 } else if( widget == cancel ) {
165 ui->handleOnly( 0x0 );
166 visible( false );
167 value( 0.f );
168
169 callback( this, ui );
170 } else {
171 //printf("Dialog::widgetValueCB() widget %s\n", widget->label() );
172 }
173 }
174
run(const char * header,const char * text,BUTTONS b,int mx_,int my_)175 void Dialog::run( const char* header, const char* text, BUTTONS b, int mx_, int my_ )
176 {
177 // show the dialog
178 label( header );
179 contents = text;
180 buttons_ = b;
181
182 ok->value( false );
183 cancel->value( false );
184
185 visible( true );
186 // position to have OK/YES under mouse cursor. When -1, ignore
187 mx = mx_;
188 my = my_;
189
190 // make UI route all events to here, and wait for the valueCB to be called to
191 // release the handleOnly
192 ui->handleOnly( this );
193 }
194