| 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