Module: environment-property-pages Synopsis: Environment property pages Author: Andy Armstrong, Chris Page Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND /// Add an elements page for collections, and make it the default define sideways method frame-property-types (frame :: , class :: subclass()) => (types :: ) concatenate(next-method(), #(#"elements")) end method frame-property-types; define sideways method frame-default-property-type (frame :: , class :: subclass()) => (type :: false-or()) #"elements" end method frame-default-property-type; /// Collection wrapper // // This object encapsulates a key and matching element from a collection define constant = type-union(, , ); define abstract sealed class () end class ; define sealed domain make (singleton()); define sealed domain initialize (); define sealed class () sealed constant slot wrapper-key :: , required-init-keyword: key:; end class ; define sealed class () sealed constant slot wrapper-key :: , required-init-keyword: key:; end class ; define sealed class () sealed constant slot wrapper-key :: , required-init-keyword: key:; end class ; define method frame-collection-contents (frame :: , collection :: ) => (contents :: ) let project = frame.ensure-frame-project; let size = frame-element-count(frame, collection); let element-range = range(from: 0, below: size); let keys = collection-keys(project, collection, range: element-range); let elements = collection-elements(project, collection, range: element-range); map(method (key :: , element :: ) => (wrapper :: ) let class = select (collection by instance?) => ; => ; => ; //---*** andrewa: shouldn't be necessary, but is... => ; end; make(class, key: key, object: element) end, keys, elements) end method frame-collection-contents; //--- Ultimately this should probably be a registry setting define constant $maximum-elements = 5000; define method frame-element-count (frame :: , object :: ) => (new-size :: ) let project = frame.ensure-frame-project; let size = collection-size(project, object); if (size > $maximum-elements & environment-question (format-to-string ("There are %d elements in '%s', show just the first %d?", size, frame-object-unique-name(frame, object), $maximum-elements), owner: frame)) $maximum-elements else size end end method frame-element-count; define method frame-sort-collection-contents (frame :: , contents :: , order :: ) => (contents :: ) local method environment-object-key (object :: ) => (label :: ) frame-print-collection-content(frame, object) end method environment-object-key; local method collection-label-key (wrapper :: ) => (label :: type-union(, )) let key = wrapper.wrapper-key; select (key by instance?) => environment-object-key(key); , => key; end end method collection-label-key; select (order) #"key" => frame-sort-items(frame, contents, label-key: collection-label-key); #"reverse-key" => frame-sort-items(frame, contents, label-key: collection-label-key, test: \>); #"element" => frame-sort-items (frame, contents, key: wrapper-object, label-key: curry(frame-print-collection-content, frame)); end end method frame-sort-collection-contents; /// Elements property page define sideways method make-frame-property-page-displayer (frame :: , class :: subclass(), type == #"elements") => (label :: , displayer :: ) let project = frame.ensure-frame-project; let displayer = make(, element-label: "element", information-available?-function: curry(application-tethered?, project), transaction-function: curry(perform-application-transaction, project), children-generator: curry(frame-collection-contents, frame), headings: #["Key", "Element"], widths: #[200, 1000], sort-orders: #[#[#"key", #"reverse-key"], #"element"], sort-order: #"key", sort-function: curry(frame-sort-collection-contents, frame), generators: vector(identity, wrapper-object), label-key: curry(frame-print-collection-content, frame)); values("Elements", displayer) end method make-frame-property-page-displayer; define method frame-print-collection-content (frame :: , object :: ) => (string :: ) frame-print-environment-object(frame, object) end method frame-print-collection-content; define method frame-print-collection-content (frame :: , wrapper :: ) => (string :: ) let project = frame.ensure-frame-project; let key = wrapper.wrapper-key; select (key by instance?) => frame-print-collection-content(frame, key); => key; otherwise => format-to-string("%=", key); end end method frame-print-collection-content; /// Browsing of collection entries define method frame-browse-collection-wrapper-key (frame :: , target :: ) => () let pane = target.target-pane; let wrapper = target.target-object; let key = wrapper.wrapper-key; frame-browse-target(frame, target: make-command-target(pane, key)) end method frame-browse-collection-wrapper-key; define function frame-browse-target-key (frame :: ) => () frame-browse-collection-wrapper-key(frame, frame.frame-command-target) end function frame-browse-target-key; define constant $browse-target-key-doc = "Opens a browser on the key for the selected element."; define constant $browse-target-key-command = make-command-decorator("Browse Key", frame-browse-target-key, documentation: $browse-target-key-doc); define command-table *explicit-key-collection-browse-popup-menu-command-table* (*global-command-table*) command $describe-target-command; command $browse-target-command; command $browse-target-type-command; command $browse-target-key-command; end command-table *explicit-key-collection-browse-popup-menu-command-table*; define command-table *explicit-key-collection-popup-menu-command-table* (*global-command-table*) include *explicit-key-collection-browse-popup-menu-command-table*; include *popup-menu-edit-command-table*; include *popup-menu-documentation-command-table*; include *popup-menu-clipboard-command-table*; include *popup-menu-properties-command-table*; end command-table *explicit-key-collection-popup-menu-command-table*; define method command-table-for-target (frame :: , wrapper :: ) => (comtab :: ) if (instance?(wrapper.wrapper-key, )) *explicit-key-collection-popup-menu-command-table* else next-method() end end method command-table-for-target;