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 683 683: def initialize(window) 684: @window = window 685: super(TreeStore.new(Gdk::Pixbuf, String, String)) 686: self.selection.mode = SELECTION_BROWSE 687: 688: @expanded = false 689: self.headers_visible = false 690: add_columns 691: add_popup_menu 692: end
Ask for an element to be appended parent.
# File lib/json/editor.rb, line 877 877: def ask_for_element(parent = nil, default_type = nil, value_text = @content) 878: type_input = value_input = nil 879: 880: dialog = Dialog.new( 881: "New element into #{parent ? parent.type : 'root'}", 882: nil, nil, 883: [ Stock::OK, Dialog::RESPONSE_ACCEPT ], 884: [ Stock::CANCEL, Dialog::RESPONSE_REJECT ] 885: ) 886: hbox = HBox.new(false, 5) 887: hbox.add(Label.new("Type:")) 888: hbox.pack_start(type_input = ComboBox.new(true)) 889: default_active = 0 890: types = parent ? ALL_TYPES : CONTAINER_TYPES 891: types.each_with_index do |t, i| 892: type_input.append_text(t) 893: if t == default_type 894: default_active = i 895: end 896: end 897: type_input.active = default_active 898: dialog.vbox.add(hbox) 899: type_input.signal_connect(:changed) do 900: configure_value(value_input, types[type_input.active]) 901: end 902: 903: hbox = HBox.new(false, 5) 904: hbox.add(Label.new("Value:")) 905: hbox.pack_start(value_input = Entry.new) 906: value_input.text = value_text if value_text 907: configure_value(value_input, types[type_input.active]) 908: 909: dialog.vbox.add(hbox) 910: 911: dialog.signal_connect('key-press-event''key-press-event', &DEFAULT_DIALOG_KEY_PRESS_HANDLER) 912: dialog.show_all 913: self.focus = dialog 914: dialog.run do |response| 915: if response == Dialog::RESPONSE_ACCEPT 916: type = types[type_input.active] 917: @content = case type 918: when 'Numeric' 919: Integer(value_input.text) rescue Float(value_input.text) rescue 0 920: else 921: value_input.text 922: end.to_s 923: return type, @content 924: end 925: end 926: return 927: ensure 928: dialog.destroy if dialog 929: end
Ask for a find term to search for in the tree. Returns the term as a string.
# File lib/json/editor.rb, line 966 966: def ask_for_find_term 967: dialog = Dialog.new( 968: "Find a node matching regex in tree.", 969: nil, nil, 970: [ Stock::OK, Dialog::RESPONSE_ACCEPT ], 971: [ Stock::CANCEL, Dialog::RESPONSE_REJECT ] 972: ) 973: hbox = HBox.new(false, 5) 974: 975: hbox.add(Label.new("Regex:")) 976: hbox.pack_start(regex_input = Entry.new) 977: regex_input.text = @regex || '' 978: 979: dialog.vbox.add(hbox) 980: 981: dialog.signal_connect('key-press-event''key-press-event', &DEFAULT_DIALOG_KEY_PRESS_HANDLER) 982: dialog.show_all 983: self.focus = dialog 984: dialog.run do |response| 985: if response == Dialog::RESPONSE_ACCEPT 986: return @regex = regex_input.text 987: end 988: end 989: return 990: ensure 991: dialog.destroy if dialog 992: end
Ask for a hash key, value pair to be added to the Hash node parent.
# File lib/json/editor.rb, line 808 808: def ask_for_hash_pair(parent) 809: key_input = type_input = value_input = nil 810: 811: dialog = Dialog.new("New (key, value) pair for Hash", nil, nil, 812: [ Stock::OK, Dialog::RESPONSE_ACCEPT ], 813: [ Stock::CANCEL, Dialog::RESPONSE_REJECT ] 814: ) 815: 816: hbox = HBox.new(false, 5) 817: hbox.pack_start(Label.new("Key:")) 818: hbox.pack_start(key_input = Entry.new) 819: key_input.text = @key || '' 820: dialog.vbox.add(hbox) 821: key_input.signal_connect(:activate) do 822: if parent.any? { |c| c.content == key_input.text } 823: toplevel.display_status('Key already exists in Hash!') 824: key_input.text = '' 825: else 826: toplevel.display_status('Key has been changed.') 827: end 828: end 829: 830: hbox = HBox.new(false, 5) 831: hbox.add(Label.new("Type:")) 832: hbox.pack_start(type_input = ComboBox.new(true)) 833: ALL_TYPES.each { |t| type_input.append_text(t) } 834: type_input.active = @type || 0 835: dialog.vbox.add(hbox) 836: 837: type_input.signal_connect(:changed) do 838: value_input.editable = false 839: case ALL_TYPES[type_input.active] 840: when 'Array', 'Hash' 841: value_input.text = '' 842: when 'TrueClass' 843: value_input.text = 'true' 844: when 'FalseClass' 845: value_input.text = 'false' 846: when 'NilClass' 847: value_input.text = 'null' 848: else 849: value_input.text = '' 850: value_input.editable = true 851: end 852: end 853: 854: hbox = HBox.new(false, 5) 855: hbox.add(Label.new("Value:")) 856: hbox.pack_start(value_input = Entry.new) 857: value_input.text = @value || '' 858: dialog.vbox.add(hbox) 859: 860: dialog.signal_connect('key-press-event''key-press-event', &DEFAULT_DIALOG_KEY_PRESS_HANDLER) 861: dialog.show_all 862: self.focus = dialog 863: dialog.run do |response| 864: if response == Dialog::RESPONSE_ACCEPT 865: @key = key_input.text 866: type = ALL_TYPES[@type = type_input.active] 867: content = value_input.text 868: return @key, type, content 869: end 870: end 871: return 872: ensure 873: dialog.destroy 874: 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 934 934: def ask_for_order 935: dialog = Dialog.new( 936: "Give an order criterium for 'x'.", 937: nil, nil, 938: [ Stock::OK, Dialog::RESPONSE_ACCEPT ], 939: [ Stock::CANCEL, Dialog::RESPONSE_REJECT ] 940: ) 941: hbox = HBox.new(false, 5) 942: 943: hbox.add(Label.new("Order:")) 944: hbox.pack_start(order_input = Entry.new) 945: order_input.text = @order || 'x' 946: 947: hbox.pack_start(reverse_checkbox = CheckButton.new('Reverse')) 948: 949: dialog.vbox.add(hbox) 950: 951: dialog.signal_connect('key-press-event''key-press-event', &DEFAULT_DIALOG_KEY_PRESS_HANDLER) 952: dialog.show_all 953: self.focus = dialog 954: dialog.run do |response| 955: if response == Dialog::RESPONSE_ACCEPT 956: return @order = order_input.text, reverse_checkbox.active? 957: end 958: end 959: return 960: ensure 961: dialog.destroy if dialog 962: 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 794 794: def create_node(parent, type, content) 795: iter = if parent 796: model.append(parent) 797: else 798: new_model = Editor.data2model(nil) 799: toplevel.view_new_model(new_model) 800: new_model.iter_first 801: end 802: iter.type, iter.content = type, content 803: expand_collapse(parent) if parent 804: iter 805: end
Expand or collapse row pointed to by iter according to the expanded attribute.
# File lib/json/editor.rb, line 996 996: def expand_collapse(iter) 997: if expanded 998: expand_row(iter.path, true) 999: else 1000: collapse_row(iter.path) 1001: end 1002: end
# File lib/json/editor.rb, line 702 702: def add_columns 703: cell = CellRendererPixbuf.new 704: column = TreeViewColumn.new('Icon', cell, 705: 'pixbuf' => ICON_COL 706: ) 707: append_column(column) 708: 709: cell = CellRendererText.new 710: column = TreeViewColumn.new('Type', cell, 711: 'text' => TYPE_COL 712: ) 713: append_column(column) 714: 715: cell = CellRendererText.new 716: cell.editable = true 717: column = TreeViewColumn.new('Content', cell, 718: 'text' => CONTENT_COL 719: ) 720: cell.signal_connect(:edited, &method(:cell_edited)) 721: append_column(column) 722: end
# File lib/json/editor.rb, line 784 784: def add_popup_menu 785: menu = PopUpMenu.new(self) 786: menu.create 787: end
# File lib/json/editor.rb, line 737 737: def cell_edited(cell, path, value) 738: iter = model.get_iter(path) 739: case iter.type 740: when 'Key' 741: unify_key(iter, value) 742: toplevel.display_status('Key has been changed.') 743: when 'FalseClass' 744: value.downcase! 745: if value == 'true' 746: iter.type, iter.content = 'TrueClass', 'true' 747: end 748: when 'TrueClass' 749: value.downcase! 750: if value == 'false' 751: iter.type, iter.content = 'FalseClass', 'false' 752: end 753: when 'Numeric' 754: iter.content = (Integer(value) rescue Float(value) rescue 0).to_s 755: when 'String' 756: iter.content = value 757: when 'Hash', 'Array' 758: return 759: else 760: fail "Unknown type found in model: #{iter.type}" 761: end 762: window.change 763: end
# File lib/json/editor.rb, line 765 765: def configure_value(value, type) 766: value.editable = false 767: case type 768: when 'Array', 'Hash' 769: value.text = '' 770: when 'TrueClass' 771: value.text = 'true' 772: when 'FalseClass' 773: value.text = 'false' 774: when 'NilClass' 775: value.text = 'null' 776: when 'Numeric', 'String' 777: value.text ||= '' 778: value.editable = true 779: else 780: raise ArgumentError, "unknown type '#{type}' encountered" 781: end 782: end
# File lib/json/editor.rb, line 724 724: def unify_key(iter, key) 725: return unless iter.type == 'Key' 726: parent = iter.parent 727: if parent.any? { |c| c != iter and c.content == key } 728: old_key = key 729: i = 0 730: begin 731: key = sprintf("%s.%d", old_key, i += 1) 732: end while parent.any? { |c| c != iter and c.content == key } 733: end 734: iter.content = key 735: end