1 module ui.dialog_slice; 2 3 import gtk.Builder, gtk.Widget, gtk.Window, gdk.Event; 4 import gtk.Container, gtk.Grid; 5 import gtk.Label, gtk.Adjustment, gtk.SpinButton; 6 7 import std.conv, std.algorithm, std.math; 8 9 public import gtkc.gtktypes, gtk.Dialog; 10 11 /** 12 * Custom FileChooserDialog that select a file for open or save data for FCPU-16 13 */ 14 class dialog_slice : Dialog{ 15 private: 16 Builder builder; /// Builder used to load from xml file the file options widget 17 18 Label lbl_text; /// Label showing informative text 19 20 Label lbl_maxsize; /// Max size (max diference) of the slice 21 Label lbl_size; /// Actual size (diference) of the slice 22 SpinButton spin_begin; /// Spin button selecting the begin address of a slice 23 SpinButton spin_end; /// Spin button selecting the end address of a slice 24 25 size_t max_dif; /// Max diference between adresses 26 size_t top; /// Top address 27 bool sbyte; /// Show number of bytes or number of glyphs 28 Adjustment adjust_beg_addr; /// Controls begin address spin button 29 Adjustment adjust_end_addr; /// Controls end address spin button 30 31 public: 32 33 /** 34 * See: gtk.Dialog; 35 * Params: 36 * text = Texto to be showed over the controls describing what the user are to do 37 * size = Top address 38 * max_size = Max size of the slice selection 39 * sbyte = If it's TRUE, show number of bytes, else show number of glyphs 40 */ 41 this (string title, Window parent, GtkDialogFlags flags, string text, size_t top = 0xFFFF , size_t max_size = 255, bool sbyte = true) { 42 super(title, parent, flags, [StockID.OK, StockID.CANCEL], [ResponseType.ACCEPT, ResponseType.CANCEL]); 43 44 this.top = top; 45 this.max_dif = max_size; 46 this.sbyte = sbyte; 47 // Adds the text label 48 lbl_text = new Label(text); 49 this.getContentArea().packStart(lbl_text, false, true, 10); 50 lbl_text.setPadding(5, 0); 51 lbl_text.setAlignment(0, 0.5); 52 lbl_text.show(); 53 54 // Load widgets from file 55 builder = new Builder (); 56 if (! builder.addFromString (import("slice.ui"))) { 57 throw new Exception("Can't find file slice.ui"); 58 } 59 60 // Gets every object 61 auto table= cast(Grid) builder.getObject ("table"); 62 if (table is null) { 63 throw new Exception("Can't find table widget"); 64 } 65 Label lbl_maxsize= cast(Label) builder.getObject ("lbl_maxsize"); 66 if (lbl_maxsize is null) { 67 throw new Exception("Can't find lbl_maxsize widget"); 68 } 69 70 Label lbl_size= cast(Label) builder.getObject ("lbl_size"); 71 if (lbl_size is null) { 72 throw new Exception("Can't find lbl_size widget"); 73 } 74 75 SpinButton spin_begin= cast(SpinButton) builder.getObject ("spin_begin"); 76 if (spin_begin is null) { 77 throw new Exception("Can't find spin_begin widget"); 78 } 79 80 SpinButton spin_end= cast(SpinButton) builder.getObject ("spin_end"); 81 if (spin_end is null) { 82 throw new Exception("Can't find spin_end widget"); 83 } 84 // Set and assigns attributes of each widget ******************************* 85 // Attach table container to the Dialog 86 table.reparent(this); 87 this.getContentArea().packEnd(table, false, true, 10); 88 89 // Create the adjusment objects and assign it to the spin buttons 90 adjust_beg_addr = new Adjustment(0, 0, max_dif -1, 1 , 10, 0); 91 adjust_end_addr = new Adjustment(max_dif, 1, max_dif , 1 , 10, 0); 92 93 spin_begin.configure(adjust_beg_addr, 0, 0); 94 spin_end.configure(adjust_end_addr, 0, 0); 95 96 // Show max size and actual size 97 lbl_maxsize.setLabel(to!string(top)); 98 auto s = adjust_end_addr.getValue() - adjust_beg_addr.getValue() +1; 99 if (!sbyte) { 100 lbl_size.setText(to!string(s) ~ " words" ~ " - " 101 ~ to!string(floor(cast(double)(max_dif/2))) ~ " glyphs "); 102 } else { 103 lbl_size.setText(to!string(s) ~ " words" ~ " - " 104 ~ to!string(s*2) ~ " bytes "); 105 } 106 107 // Signal handlers ********************************************************* 108 // Begin of slice being edited 109 adjust_beg_addr.addOnValueChanged( (Adjustment ad) { 110 adjust_end_addr.setLower(min(ad.getValue() +1, top)); 111 adjust_end_addr.setUpper(min(ad.getValue() +255, top)); 112 if (adjust_end_addr.getValue() < (ad.getValue() +1)) { 113 adjust_end_addr.setValue(ad.getValue() +1); 114 } 115 auto s = adjust_end_addr.getValue() - adjust_beg_addr.getValue() +1; 116 if (!sbyte) { 117 lbl_size.setText(to!string(s) ~ " words" ~ " - " 118 ~ to!string(floor(s/2)) ~ " glyphs "); 119 } else { 120 lbl_size.setText(to!string(s) ~ " words" ~ " - " 121 ~ to!string(s*2) ~ " bytes "); 122 } 123 }); 124 125 // End of slice being edited 126 adjust_end_addr.addOnValueChanged( (Adjustment ad) { 127 adjust_end_addr.setLower(adjust_beg_addr.getValue() +1); 128 adjust_beg_addr.setUpper(max(ad.getValue() -1, 0)); 129 if (adjust_beg_addr.getValue() > (ad.getValue() -1)) { 130 adjust_beg_addr.setValue(ad.getValue() -1); 131 } 132 auto s = adjust_end_addr.getValue() - adjust_beg_addr.getValue() +1; 133 if (!sbyte) { 134 lbl_size.setText(to!string(s) ~ " words" ~ " - " 135 ~ to!string(floor(s/2)) ~ " glyphs "); 136 } else { 137 lbl_size.setText(to!string(s) ~ " words" ~ " - " 138 ~ to!string(s*2) ~ " bytes "); 139 } 140 }); 141 } 142 143 /// Return the selected bottom address 144 auto bottom_address() @property { 145 return adjust_beg_addr.getValue(); 146 } 147 148 /// Return the selected top address 149 auto top_address() @property { 150 return adjust_end_addr.getValue(); 151 } 152 153 /// Return the size of the selected slice (including the last address) 154 auto size() @property { 155 return adjust_end_addr.getValue() - adjust_beg_addr.getValue() +1; 156 } 157 } 158 159 unittest { 160 import std.stdio, gtk.Main; 161 162 Main.init([""]); 163 164 auto d = new dialog_slice("test", null, GtkDialogFlags.MODAL, "This is a test", 1024); 165 166 writeln(d.run()); 167 writeln("Begin: ", d.bottom_address); 168 writeln("End: ", d.top_address); 169 writeln("Size (including end address): ", d.size); 170 171 }