;;; -*- Mode: LISP; Syntax: Common-Lisp; Package: LAPIDARY; Base: 10 -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; The Garnet User Interface Development Environment. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; This code was written as part of the Garnet project at ;;; ;;; Carnegie Mellon University, and has been placed in the public ;;; ;;; domain. If you are using this code or any part of Garnet, ;;; ;;; please contact garnet@cs.cmu.edu to be put on the mailing list. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #| ============================================================ Change log: 7/6/92 Brad Vander Zanden -- added a new function, restore-line-props, that restores defaults when there is a selected object. Also added code to save defaults when there is a selected object. 5/08/92 Martin Sjolin -- ext:ignore-errors --> ignore-errors 5/27/91 Brad Vander Zanden -- created ============================================================ |# (in-package "LAPIDARY") ;;; Set the value slot, but first make sure that formulas are set up by ;;; calling g-value (defun Init-Value (obj new-val) (g-value obj :value) ; need to do this to set up the dependencies (s-value obj :value new-val)) (defun Line-or-Fill-New-Style (prop slot1 slot2 agg-of-choices default-when-bad slots-to-change) (let* ((obj (g-value prop :current-val)) (cur-style (g-value obj slot1)) (other-style (g-value obj slot2)) (color-to-use (g-value prop :new-color)) (style-selection (or (g-value agg-of-choices :selected) (g-value agg-of-choices :default))) (style-to-use (g-value style-selection :val)) (error-obj (g-value prop :error))) (opal:update-all) ; try to separate the previous changes from the ; changes to the new object to avoid flicker (s-value error-obj :visible NIL) (if (or (null style-to-use) (eq :none style-to-use)) (progn (when cur-style (s-value obj :other2-style cur-style)) (s-value obj slot1 NIL)) ;; else there is a style (progn (if (is-a-p style-to-use opal:graphic-quality) (progn (s-value other-style :foreground-color color-to-use) (s-value error-obj :visible NIL)) ; else bad style, from "other" (progn (s-value error-obj :visible T) (setq style-to-use default-when-bad))) (unless cur-style ; if nil then get it from "other2" (setq cur-style (g-value obj :other2-style))) (dolist (slot slots-to-change) (s-value other-style slot (g-value style-to-use slot))) (s-value obj slot1 other-style) (s-value obj slot2 cur-style))))) (defun careful-eval (string) (multiple-value-bind (val errorp) #+cmu (ignore-errors (read-from-string string)) #+lcl3.0 (system::ignore-errors (read-from-string string)) #+allegro (excl::ignore-errors (read-from-string string)) #-(or cmu lcl3.0 allegro) (read-from-string string) ; don't know the handler (if (numberp errorp) ; then no error (progn (when (or (and (symbolp val)(boundp val)) ; if a symbol or list, eval it (listp val)) (setq val (eval val)) )) (progn ; error, just use string (setq val string))) val)) ;;; This is called when there is a new line style, so the final line style ;;; line can be changed (defun New-Line-Style (&rest args) (declare (special line-prop)) (declare (ignore args)) (Line-or-Fill-New-Style line-prop :line-style :other-line-style (g-value line-prop :line-style-boxes) opal:dashed-line '(:line-thickness :line-style :dash-pattern :stipple))) ;;; This is called as the OK function when a new color is picked. It changes the ;;; color slot and line. (defun Line-Color-OK (new-color) (declare (special line-prop)) (s-value line-prop :new-color new-color) (use-color (g-value line-prop :current-color) new-color) ; if the line-style was :none, change it to be black, since usually ; wouldn't change the color and not want to use it (let ((cur-line (g-value line-prop :line-style-boxes :selected))) (cond ((eq cur-line (g-value line-prop :line-style-boxes :NON-BOX)) (Inter:SelectObj (g-value line-prop :press) (g-value line-prop :line-style-boxes :LINE0-BOX))) ;; if a constraint used to be in place, select the appropriate ;; line style ((and (null cur-line) (g-value line-prop :constraint-button :selected)) (let ((default-line (g-value line-prop :line-style-boxes :default))) (if (eq default-line (g-value line-prop :line-style-boxes :NON-BOX)) (Inter:SelectObj (g-value line-prop :press) (g-value line-prop :line-style-boxes :line0-box)) (Inter:SelectObj (g-value line-prop :press) default-line)))))) (new-line-style)) ;;; This is called when the color button is hit to create the color dialog box. (defun COLOR-PROP-From-Line-Or-Fill (gadget value) (declare (special line-prop)) (declare (ignore value)) (let* ((prop (g-value gadget :parent)) (old-color (g-value prop :new-color)) (Color-OK (g-value prop :color-ok-func))) (multiple-value-bind (left top) (opal:convert-coordinates (g-value gadget :window) (g-value gadget :left) (opal:bottom gadget) NIL) (Show-Color-Prop old-color left (+ top 10) Color-OK)))) (defparameter Color-To-Line-Mapping `((,opal:black . ,opal:line-0) (,opal:red . ,opal:red-line) (,opal:green . ,opal:green-line) (,opal:blue . ,opal:blue-line) (,opal:yellow . ,opal:yellow-line) (,opal:purple . ,opal:purple-line) (,opal:cyan . ,opal:cyan-line) (,opal:orange . ,opal:orange-line))) ;; If the color is black, use the line style specified. Otherwise, if ;; the line style is line0 and there is a color, see if can use one ;; of the standard opal line-styles. Otherwise, create a new line style ;; object (defun Check-Colors-For-Line (new-line-style new-color sel-obj) (declare (special line-prop)) (let (val) (cond ((null new-line-style) NIL) ((eq new-color opal:black) new-line-style) ((and (eq new-line-style opal:line-0) (setq val (cdr (assoc new-color Color-To-Line-Mapping)))) val) ;; next check if have the value typed into Other, with no color change ((and (eq sel-obj (g-value line-prop :line-style-boxes :Other-box)) (eq new-color (g-value new-line-style :foreground-color))) new-line-style) (T ; otherwise, create a line style (create-instance NIL opal:line-style (:lapidary-val new-line-style) (:foreground-color new-color) (:line-thickness (g-value new-line-style :line-thickness)) (:cap-style (g-value new-line-style :cap-style)) (:join-style (g-value new-line-style :join-style)) (:line-style (g-value new-line-style :line-style)) (:dash-pattern (g-value new-line-style :dash-pattern)) (:stipple (g-value new-line-style :stipple))))))) ;; Main OK procedure; Sets the object's line-style slot. (defun line-prop-ok (top-gadget values) (declare (special line-prop)) (declare (ignore values)) (let ((newsel (g-value top-gadget :line-style-boxes :selected)) (slot (g-value top-gadget :for-slot)) (constraint-p (g-value top-gadget :constraint-button :selected)) val) (if (null newsel) (if constraint-p (setf val (g-value top-gadget :constraint-button :val)) (error "Nothing selected for line-prop")) (progn (setq val (g-value newsel :val)) (when (null val) (Error "no value in newsel ~s" newsel)))) (when (eq val :none) (setq val NIL)) ; (reset-undo) (when (null constraint-p) (setq val (Check-Colors-For-Line val (g-value line-prop :new-color) newsel)) ;; do nothing if the line-style is a string--this means there ;; was an error in the other box (when (not (stringp val)) (dolist (obj (g-value *selection-info* :selected)) ; (undo-save obj slot) (destroy-constraint obj slot) (s-value obj slot val)))) ;; if there is a selection, restore the original values (restore-line-props) )) ;; if there is a selection, restore the original values--we only want ;; the current line-style to change if the user changes it when there ;; are no selections (defun restore-line-props (&rest args) (declare (ignore args)) (declare (special line-prop)) ; (undo) (when (g-value lapidary::*selection-info* :selected) (s-value (g-value line-prop :constraint-button) :selected nil) (s-value (g-value line-prop :line-style-boxes) :selected (g-value line-prop :save-selected)) (s-value line-prop :other-val (g-value line-prop :save-other-val)) (s-value line-prop :other-box (g-value line-prop :save-other-box)) (s-value line-prop :new-color (g-value line-prop :save-new-color)) (s-value line-prop :current-color (g-value line-prop :save-current-color)) (s-value line-prop :default (g-value line-prop :save-default)) (new-line-style))) ;; Given a style, see if it is one of the standard choices (defun find-obj-for-style (agg-of-choices style) (dolist (obj (g-value agg-of-choices :components)) (when (eq style (g-value obj :val)) (return-from find-obj-for-style obj)))) ;; If an opal color line style, then returns the line-0 box, otherwise ;; checks if a created line style using one of the standard patterns. ;; Call this if not one of the standard line styles (defun Check-Lines-For (new-line-style) (declare (special line-prop)) (let ((val (car (rassoc new-line-style Color-To-line-Mapping)))) (if val ; then return line-0 (setq val (g-value line-prop :line-style-boxes :LINE0-BOX)) (progn (setq val (g-value new-line-style :lapidary-val)) (when val (setq val (find-obj-for-style (g-value line-prop :line-style-boxes) val))))) val)) ;;;Main procedure to show the dialog box set up for the return (defun Show-Line-Props-Dialog (left top slot) (declare (special line-prop)) (let* ((for-obj (car (g-value *selection-info* :selected))) (style (cond (for-obj (g-value for-obj slot)) ((g-value line-prop :window) :default) (t opal:line-0))) (other-val (g-value line-prop :other-val)) (other-box (g-value line-prop :line-style-boxes :Other-box)) (new-color (cond ((schema-p style) (or (g-value style :foreground-color) (g-value line-prop :new-color))) (t (g-value line-prop :new-color)))) initial-selection) ;; if there is a selection, save the current values so they can be ;; restored once the line-style of the selection has been changed (when for-obj (s-value line-prop :save-selected (g-value line-prop :line-style-boxes :selected)) (s-value line-prop :save-other-val other-val) (s-value line-prop :save-other-box other-box) (s-value line-prop :save-new-color (g-value line-prop :new-color)) (s-value line-prop :save-current-color (g-value line-prop :current-color)) (s-value line-prop :save-default (g-value line-prop :default))) (cond ((null style) (setq style :none)) ((or (eq style opal:line-1) (eq style opal:default-line-style)) (setq style opal:line-0))) (s-value line-prop :for-obj for-obj) (s-value line-prop :for-slot slot) (s-value line-prop :new-color new-color) (use-color (g-value line-prop :current-color) new-color) (setq initial-selection (cond ((eq style :default) style) (t (find-obj-for-style (g-value line-prop :line-style-boxes) style)))) (init-value other-val "") ; remove the string in :other (when (or (null initial-selection) ; use the "other" box (eq initial-selection other-box)) ;; first check if a special colored line (unless (setq initial-selection (Check-Lines-For style)) ;; use "Other" (setq initial-selection other-box) ;mk-string is in prop-sheet (init-value other-val (if (stringp style) style (let ((kr::*print-as-structure* nil)) (prin1-to-string style)))))) (cond ((and for-obj (formula-p (get-value for-obj :line-style))) (s-value (g-value line-prop :constraint-button) :val nil) ;; make sure the function that sets new line styles can ;; find the style if the user replaces the constraint with ;; a color (s-value (g-value line-prop :line-style-boxes) :default initial-selection) (inter:SelectObj (g-value line-prop :press) nil) (new-line-style)) ((eq initial-selection :default) t) (t (inter:SelectObj (g-value line-prop :press) initial-selection) (New-Line-style))) (gilt:show-in-window line-prop left top t) )) (defun props-constraint-final-fn (gadget value) (declare (ignore value)) (declare (special *selection-info*)) ;; determine if there is a selection (let ((selected (g-value *selection-info* :selected)) (slot (g-value gadget :slot))) (if selected (progn ;; deselect the item in the menu gadget (s-value (g-value gadget :menu-gadget) :selected nil) ;; get the top-level gadget and execute the cancel code. we ;; want to pass control to c32 and this is the best way to ;; clean up and do it (gilt::standard-cancel-function (g-value gadget :parent)) ;; get the custom constraint (gg:c32 (car selected) slot)) ;; else there is no selection--deselect the constraint button (s-value gadget :selected nil))))