Class | JSONTreeView |
In: |
lib/json/editor.rb
|
Parent: | Gtk::TreeView |
This class inherits from Gtk::TreeView, to configure it and to add a lot of behaviour to it.
expanded | [RW] | Returns true, if nodes are autoexpanding, false otherwise. |
window | [R] | Returns the MainWindow instance of this JSONTreeView. |
Creates a JSONTreeView instance, the parameter window is a MainWindow instance and used for self delegation.
# File lib/json/editor.rb, line 701 701: def initialize(window) 702: @window = window 703: super(TreeStore.new(Gdk::Pixbuf, String, String)) 704: self.selection.mode = SELECTION_BROWSE 705: 706: @expanded = false 707: self.headers_visible = false 708: add_columns 709: add_popup_menu 710: end
Ask for an element to be appended parent.
# File lib/json/editor.rb, line 902 902: def ask_for_element(parent = nil, default_type = nil, value_text = @content) 903: type_input = value_input = nil 904: 905: dialog = Dialog.new( 906: "New element into #{parent ? parent.type : 'root'}", 907: nil, nil, 908: [ Stock::OK, Dialog::RESPONSE_ACCEPT ], 909: [ Stock::CANCEL, Dialog::RESPONSE_REJECT ] 910: ) 911: hbox = HBox.new(false, 5) 912: hbox.pack_start(Label.new("Type:"), false) 913: hbox.pack_start(type_input = ComboBox.new(true)) 914: default_active = 0 915: types = parent ? ALL_TYPES : CONTAINER_TYPES 916: types.each_with_index do |t, i| 917: type_input.append_text(t) 918: if t == default_type 919: default_active = i 920: end 921: end 922: type_input.active = default_active 923: dialog.vbox.pack_start(hbox, false) 924: type_input.signal_connect(:changed) do 925: configure_value(value_input, types[type_input.active]) 926: end 927: 928: hbox = HBox.new(false, 5) 929: hbox.pack_start(Label.new("Value:"), false) 930: hbox.pack_start(value_input = Entry.new) 931: value_input.width_chars = 60 932: value_input.text = value_text if value_text 933: configure_value(value_input, types[type_input.active]) 934: 935: dialog.vbox.pack_start(hbox, false) 936: 937: dialog.signal_connect('key-press-event''key-press-event', &DEFAULT_DIALOG_KEY_PRESS_HANDLER) 938: dialog.show_all 939: self.focus = dialog 940: dialog.run do |response| 941: if response == Dialog::RESPONSE_ACCEPT 942: type = types[type_input.active] 943: @content = case type 944: when 'Numeric' 945: if (t = value_input.text) == 'Infinity' 946: 1 / 0.0 947: else 948: Integer(t) rescue Float(t) rescue 0 949: end 950: else 951: value_input.text 952: end.to_s 953: return type, @content 954: end 955: end 956: return 957: ensure 958: dialog.destroy if dialog 959: end
Ask for a find term to search for in the tree. Returns the term as a string.
# File lib/json/editor.rb, line 997 997: def ask_for_find_term(search = nil) 998: dialog = Dialog.new( 999: "Find a node matching regex in tree.", 1000: nil, nil, 1001: [ Stock::OK, Dialog::RESPONSE_ACCEPT ], 1002: [ Stock::CANCEL, Dialog::RESPONSE_REJECT ] 1003: ) 1004: hbox = HBox.new(false, 5) 1005: 1006: hbox.pack_start(Label.new("Regex:"), false) 1007: hbox.pack_start(regex_input = Entry.new) 1008: hbox.pack_start(icase_checkbox = CheckButton.new('Icase'), false) 1009: regex_input.width_chars = 60 1010: if search 1011: regex_input.text = search.source 1012: icase_checkbox.active = search.casefold? 1013: end 1014: 1015: dialog.vbox.pack_start(hbox, false) 1016: 1017: dialog.signal_connect('key-press-event''key-press-event', &DEFAULT_DIALOG_KEY_PRESS_HANDLER) 1018: dialog.show_all 1019: self.focus = dialog 1020: dialog.run do |response| 1021: if response == Dialog::RESPONSE_ACCEPT 1022: begin 1023: return Regexp.new(regex_input.text, icase_checkbox.active? ? Regexp::IGNORECASE : 0) 1024: rescue => e 1025: Editor.error_dialog(self, "Evaluation of regex /#{regex_input.text}/ failed: #{e}!") 1026: return 1027: end 1028: end 1029: end 1030: return 1031: ensure 1032: dialog.destroy if dialog 1033: end
Ask for a hash key, value pair to be added to the Hash node parent.
# File lib/json/editor.rb, line 831 831: def ask_for_hash_pair(parent) 832: key_input = type_input = value_input = nil 833: 834: dialog = Dialog.new("New (key, value) pair for Hash", nil, nil, 835: [ Stock::OK, Dialog::RESPONSE_ACCEPT ], 836: [ Stock::CANCEL, Dialog::RESPONSE_REJECT ] 837: ) 838: dialog.width_request = 640 839: 840: hbox = HBox.new(false, 5) 841: hbox.pack_start(Label.new("Key:"), false) 842: hbox.pack_start(key_input = Entry.new) 843: key_input.text = @key || '' 844: dialog.vbox.pack_start(hbox, false) 845: key_input.signal_connect(:activate) do 846: if parent.any? { |c| c.content == key_input.text } 847: toplevel.display_status('Key already exists in Hash!') 848: key_input.text = '' 849: else 850: toplevel.display_status('Key has been changed.') 851: end 852: end 853: 854: hbox = HBox.new(false, 5) 855: hbox.pack_start(Label.new("Type:"), false) 856: hbox.pack_start(type_input = ComboBox.new(true)) 857: ALL_TYPES.each { |t| type_input.append_text(t) } 858: type_input.active = @type || 0 859: dialog.vbox.pack_start(hbox, false) 860: 861: type_input.signal_connect(:changed) do 862: value_input.editable = false 863: case ALL_TYPES[type_input.active] 864: when 'Array', 'Hash' 865: value_input.text = '' 866: when 'TrueClass' 867: value_input.text = 'true' 868: when 'FalseClass' 869: value_input.text = 'false' 870: when 'NilClass' 871: value_input.text = 'null' 872: else 873: value_input.text = '' 874: value_input.editable = true 875: end 876: end 877: 878: hbox = HBox.new(false, 5) 879: hbox.pack_start(Label.new("Value:"), false) 880: hbox.pack_start(value_input = Entry.new) 881: value_input.width_chars = 60 882: value_input.text = @value || '' 883: dialog.vbox.pack_start(hbox, false) 884: 885: dialog.signal_connect('key-press-event''key-press-event', &DEFAULT_DIALOG_KEY_PRESS_HANDLER) 886: dialog.show_all 887: self.focus = dialog 888: dialog.run do |response| 889: if response == Dialog::RESPONSE_ACCEPT 890: @key = key_input.text 891: type = ALL_TYPES[@type = type_input.active] 892: content = value_input.text 893: return @key, type, content 894: end 895: end 896: return 897: ensure 898: dialog.destroy 899: end
Ask for an order criteria for sorting, using x for the element in question. Returns the order criterium, and true/false for reverse sorting.
# File lib/json/editor.rb, line 964 964: def ask_for_order 965: dialog = Dialog.new( 966: "Give an order criterium for 'x'.", 967: nil, nil, 968: [ Stock::OK, Dialog::RESPONSE_ACCEPT ], 969: [ Stock::CANCEL, Dialog::RESPONSE_REJECT ] 970: ) 971: hbox = HBox.new(false, 5) 972: 973: hbox.pack_start(Label.new("Order:"), false) 974: hbox.pack_start(order_input = Entry.new) 975: order_input.text = @order || 'x' 976: order_input.width_chars = 60 977: 978: hbox.pack_start(reverse_checkbox = CheckButton.new('Reverse'), false) 979: 980: dialog.vbox.pack_start(hbox, false) 981: 982: dialog.signal_connect('key-press-event''key-press-event', &DEFAULT_DIALOG_KEY_PRESS_HANDLER) 983: dialog.show_all 984: self.focus = dialog 985: dialog.run do |response| 986: if response == Dialog::RESPONSE_ACCEPT 987: return @order = order_input.text, reverse_checkbox.active? 988: end 989: end 990: return 991: ensure 992: dialog.destroy if dialog 993: end
Create a type node with content content, and add it to parent in the model. If parent is nil, create a new model and put it into the editor treeview.
# File lib/json/editor.rb, line 817 817: def create_node(parent, type, content) 818: iter = if parent 819: model.append(parent) 820: else 821: new_model = Editor.data2model(nil) 822: toplevel.view_new_model(new_model) 823: new_model.iter_first 824: end 825: iter.type, iter.content = type, content 826: expand_collapse(parent) if parent 827: iter 828: end
Expand or collapse row pointed to by iter according to the expanded attribute.
# File lib/json/editor.rb, line 1037 1037: def expand_collapse(iter) 1038: if expanded 1039: expand_row(iter.path, true) 1040: else 1041: collapse_row(iter.path) 1042: end 1043: end
# File lib/json/editor.rb, line 720 720: def add_columns 721: cell = CellRendererPixbuf.new 722: column = TreeViewColumn.new('Icon', cell, 723: 'pixbuf' => ICON_COL 724: ) 725: append_column(column) 726: 727: cell = CellRendererText.new 728: column = TreeViewColumn.new('Type', cell, 729: 'text' => TYPE_COL 730: ) 731: append_column(column) 732: 733: cell = CellRendererText.new 734: cell.editable = true 735: column = TreeViewColumn.new('Content', cell, 736: 'text' => CONTENT_COL 737: ) 738: cell.signal_connect(:edited, &method(:cell_edited)) 739: append_column(column) 740: end
# File lib/json/editor.rb, line 807 807: def add_popup_menu 808: menu = PopUpMenu.new(self) 809: menu.create 810: end
# File lib/json/editor.rb, line 755 755: def cell_edited(cell, path, value) 756: iter = model.get_iter(path) 757: case iter.type 758: when 'Key' 759: unify_key(iter, value) 760: toplevel.display_status('Key has been changed.') 761: when 'FalseClass' 762: value.downcase! 763: if value == 'true' 764: iter.type, iter.content = 'TrueClass', 'true' 765: end 766: when 'TrueClass' 767: value.downcase! 768: if value == 'false' 769: iter.type, iter.content = 'FalseClass', 'false' 770: end 771: when 'Numeric' 772: iter.content = 773: if value == 'Infinity' 774: value 775: else 776: (Integer(value) rescue Float(value) rescue 0).to_s 777: end 778: when 'String' 779: iter.content = value 780: when 'Hash', 'Array' 781: return 782: else 783: fail "Unknown type found in model: #{iter.type}" 784: end 785: window.change 786: end
# File lib/json/editor.rb, line 788 788: def configure_value(value, type) 789: value.editable = false 790: case type 791: when 'Array', 'Hash' 792: value.text = '' 793: when 'TrueClass' 794: value.text = 'true' 795: when 'FalseClass' 796: value.text = 'false' 797: when 'NilClass' 798: value.text = 'null' 799: when 'Numeric', 'String' 800: value.text ||= '' 801: value.editable = true 802: else 803: raise ArgumentError, "unknown type '#{type}' encountered" 804: end 805: end
# File lib/json/editor.rb, line 742 742: def unify_key(iter, key) 743: return unless iter.type == 'Key' 744: parent = iter.parent 745: if parent.any? { |c| c != iter and c.content == key } 746: old_key = key 747: i = 0 748: begin 749: key = sprintf("%s.%d", old_key, i += 1) 750: end while parent.any? { |c| c != iter and c.content == key } 751: end 752: iter.content = key 753: end