Parent

Included Modules

Files

JSON::Editor::JSONTreeView

This class inherits from Gtk::TreeView, to configure it and to add a lot of behaviour to it.

Attributes

window[R]

Returns the MainWindow instance of this JSONTreeView.

expanded[RW]

Returns true, if nodes are autoexpanding, false otherwise.

Public Class Methods

new(window) click to toggle source

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

Public Instance Methods

ask_for_element(parent = nil, default_type = nil, value_text = @content) click to toggle source

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', &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_find_term(search = nil) click to toggle source

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', &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_hash_pair(parent) click to toggle source

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', &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_order() click to toggle source

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', &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_node(parent, type, content) click to toggle source

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_collapse(iter) click to toggle source

Expand or collapse row pointed to by iter according to the # 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

Private Instance Methods

add_columns() click to toggle source
     # 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
add_popup_menu() click to toggle source
     # File lib/json/editor.rb, line 807
807:       def add_popup_menu
808:         menu = PopUpMenu.new(self)
809:         menu.create
810:       end
cell_edited(cell, path, value) click to toggle source
     # 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
configure_value(value, type) click to toggle source
     # 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
unify_key(iter, key) click to toggle source
     # 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

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.