The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

FileDialogTab.vala in libbirdfont

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of libbirdfont/FileDialogTab.vala.
Use table as windows file dialog
1 /* 2 Copyright (C) 2014 2015 Johan Mattsson 3 4 This library is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 3 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 */ 14 using Cairo; 15 using Math; 16 17 namespace BirdFont { 18 19 public class FileDialogTab : FontDisplay { 20 21 int scroll = 0; 22 int visible_rows = 0; 23 WidgetAllocation allocation; 24 Gee.ArrayList<string> files; 25 Gee.ArrayList<string> directories; 26 27 string title; 28 FileChooser action; 29 30 File current_dir; 31 32 string selected_filename; 33 TextListener listener; 34 35 private static bool has_drive_letters = false; 36 private static Gee.ArrayList<string> drive_letters; 37 38 public FileDialogTab (string title, FileChooser action) { 39 this.title = title; 40 this.action = action; 41 allocation = new WidgetAllocation (); 42 files = new Gee.ArrayList<string> (); 43 directories = new Gee.ArrayList<string> (); 44 45 selected_canvas (); 46 } 47 48 public static void add_drive_letter (char c) { 49 if (!has_drive_letters) { 50 drive_letters = new Gee.ArrayList<string> (); 51 has_drive_letters = true; 52 } 53 54 drive_letters.add (@"$((!) c.to_string ()):\\"); 55 } 56 57 public override void selected_canvas () { 58 string d; 59 show_text_area (""); 60 61 d = Preferences.get ("file_dialog_dir"); 62 63 if (d == "") { 64 d = Environment.get_home_dir (); 65 } 66 67 propagate_files (d); 68 69 update_scrollbar (); 70 redraw_area (0, 0, allocation.width, allocation.height); 71 } 72 73 public void propagate_files (string dir) { 74 FileEnumerator enumerator; 75 FileInfo? file_info; 76 string fn; 77 78 files.clear (); 79 directories.clear (); 80 81 current_dir = File.new_for_path (dir); 82 83 Preferences.set ("file_dialog_dir", dir); 84 85 if (current_dir.get_parent () != null) { 86 directories.add (".."); 87 } 88 89 try { 90 enumerator = current_dir.enumerate_children (FileAttribute.STANDARD_NAME + "," + FileAttribute.STANDARD_TYPE, 0); 91 92 while ((file_info = enumerator.next_file ()) != null) { 93 fn = ((!)file_info).get_name (); 94 if (!fn.has_prefix (".")) { 95 if (((!)file_info).get_file_type () == FileType.DIRECTORY) { 96 directories.add (fn); 97 } else { 98 files.add (fn); 99 } 100 } 101 } 102 } catch (Error e) { 103 warning (e.message); 104 } 105 106 directories.sort (); 107 108 if (has_drive_letters) { 109 for (int i = drive_letters.size - 1; i >= 0; i--) { 110 directories.insert (0, drive_letters.get (i)); 111 } 112 } 113 114 files.sort (); 115 116 scroll = 0; 117 update_scrollbar (); 118 } 119 120 public void show_text_area (string text) { 121 listener = new TextListener ("", text, this.title); 122 123 listener.signal_text_input.connect ((text) => { 124 selected_filename = text; 125 }); 126 127 listener.signal_submit.connect (() => { 128 File f; 129 130 MainWindow.get_tab_bar ().close_display (this); 131 132 if (selected_filename == "") { 133 action.cancel (); 134 } else { 135 f = get_child (current_dir, selected_filename); 136 action.file_selected ((!)f.get_path ()); 137 } 138 }); 139 140 TabContent.show_text_input (listener); 141 } 142 143 public override void draw (WidgetAllocation allocation, Context cr) { 144 double y = 75 * MainWindow.units; 145 int s = 0; 146 bool color = (scroll % 2) == 0; 147 148 this.allocation = allocation; 149 150 visible_rows = (int) (allocation.height / 18.0); 151 152 cr.save (); 153 Theme.color (cr, "Background 4"); 154 cr.rectangle (0, 0, allocation.width, allocation.height); 155 cr.fill (); 156 cr.restore (); 157 158 cr.save (); 159 Theme.color (cr, "Background 5"); 160 cr.set_font_size (12); 161 162 foreach (string file in directories) { 163 if (s++ >= scroll) { 164 draw_row (allocation, cr, file, y, color, true); 165 y += 18 * MainWindow.units; 166 color = !color; 167 } 168 } 169 170 foreach (string file in files) { 171 if (s++ >= scroll) { 172 draw_row (allocation, cr, file, y, color, false); 173 y += 18 * MainWindow.units; 174 color = !color; 175 } 176 } 177 178 cr.restore (); 179 } 180 181 private static void draw_row (WidgetAllocation allocation, Context cr, 182 string file, double y, bool color, bool dark) { 183 184 if (color) { 185 if (dark) { 186 cr.save (); 187 Theme.color (cr, "Background 8"); 188 cr.rectangle (0, y - 14 * MainWindow.units, allocation.width, 18 * MainWindow.units); 189 cr.fill (); 190 cr.restore (); 191 } else { 192 cr.save (); 193 Theme.color (cr, "Background 6"); 194 cr.rectangle (0, y - 14 * MainWindow.units, allocation.width, 18 * MainWindow.units); 195 cr.fill (); 196 cr.restore (); 197 } 198 } else { 199 if (dark) { 200 cr.save (); 201 Theme.color (cr, "Background 9"); 202 cr.rectangle (0, y - 14 * MainWindow.units, allocation.width, 18 * MainWindow.units); 203 cr.fill (); 204 cr.restore (); 205 } else { 206 cr.save (); 207 Theme.color (cr, "Foreground"); 208 cr.rectangle (0, y - 14 * MainWindow.units, allocation.width, 18 * MainWindow.units); 209 cr.fill (); 210 cr.restore (); 211 } 212 } 213 214 // text 215 cr.save (); 216 if (dark) { 217 Theme.color (cr, "Foreground Inverted Table"); 218 } 219 cr.move_to (60, y); 220 cr.set_font_size (12 * MainWindow.units); 221 cr.show_text (file); 222 cr.restore (); 223 224 } 225 226 public override void button_release (int button, double ex, double ey) { 227 int s = 0; 228 double y = 75 * MainWindow.units - 20 * MainWindow.units; 229 string selected; 230 bool dir = false; 231 File f; 232 233 selected = ""; 234 235 foreach (string d in directories) { 236 if (s++ >= scroll) { 237 y += 18 * MainWindow.units; 238 239 if (y - 10 * MainWindow.units <= ey <= y + 5 * MainWindow.units) { 240 selected = d; 241 dir = true; 242 } 243 } 244 } 245 246 foreach (string file in files) { 247 if (s++ >= scroll) { 248 y += 18 * MainWindow.units; 249 250 if (y - 10 * MainWindow.units <= ey <= y + 5 * MainWindow.units) { 251 selected = file; 252 } 253 } 254 } 255 256 if (button == 1) { 257 if (!dir) { 258 selected_filename = selected; 259 show_text_area (selected); 260 } else { 261 if (selected == "..") { 262 propagate_files ((!)((!)current_dir.get_parent ()).get_path ()); 263 } else { 264 265 if (selected.index_of (":\\") != -1) { 266 propagate_files (selected); 267 } else { 268 f = get_child (current_dir, selected); 269 propagate_files ((!) f.get_path ()); 270 } 271 } 272 } 273 } 274 275 update_scrollbar (); 276 redraw_area (0, 0, allocation.width, allocation.height); 277 } 278 279 public override void double_click (uint button, double ex, double ey) { 280 File f; 281 282 button_release ((int) button, ex, ey); 283 284 if (is_null (selected_filename)) { 285 warning ("No file."); 286 return; 287 } 288 289 if (selected_filename != "") { 290 f = get_child (current_dir, selected_filename); 291 action.file_selected ((!)f.get_path ()); 292 } 293 } 294 295 public override string get_label () { 296 return title; 297 } 298 299 public override string get_name () { 300 return "FileDialogTab"; 301 } 302 303 public override bool has_scrollbar () { 304 return true; 305 } 306 307 public override void scroll_wheel_down (double x, double y) { 308 double rows = 4.16 + files.size + directories.size; 309 scroll += 3; 310 311 if (scroll > rows - visible_rows) { 312 scroll = (int) (rows - visible_rows); 313 } 314 315 if (visible_rows > rows) { 316 scroll = 0; 317 } 318 319 update_scrollbar (); 320 redraw_area (0, 0, allocation.width, allocation.height); 321 } 322 323 public override void scroll_wheel_up (double x, double y) { 324 scroll -= 3; 325 326 if (scroll < 0) { 327 scroll = 0; 328 } 329 330 update_scrollbar (); 331 redraw_area (0, 0, allocation.width, allocation.height); 332 } 333 334 public override void update_scrollbar () { 335 double rows = 4.16 + files.size + directories.size; // 4.16 rows under the text input 336 337 if (rows == 0 || visible_rows == 0) { 338 MainWindow.set_scrollbar_size (0); 339 MainWindow.set_scrollbar_position (0); 340 } else { 341 MainWindow.set_scrollbar_size (visible_rows / rows); 342 MainWindow.set_scrollbar_position (scroll / rows); 343 } 344 } 345 346 public override void scroll_to (double percent) { 347 double rows = 4.16 + files.size + directories.size; 348 scroll = (int) (percent * rows); 349 350 if (scroll > rows - visible_rows) { 351 scroll = (int) (rows - visible_rows); 352 } 353 354 redraw_area (0, 0, allocation.width, allocation.height); 355 } 356 } 357 358 } 359