DIRECTORY ColorToolViewer, Buttons USING [Button, ButtonProc, Create], NewCGColor USING [HSVToRGB, RGBToHSV, HSLToRGB, RGBToHSL, undefined], ChoiceButtons USING [BuildEnumTypeSelection, ButtonList, EnumTypeRef, GetSelectedButton, SelectionNotifierProc, UpdateChoiceButtons], CNSColor USING [CSLToCNS, CNSToCSL, CSLChroma, CSLLightness, CSLSaturation, CSLToHSL, HSLToCSL, medium, red, vivid], ColorMap USING [SetRGBColor], Containers USING [Container, Create], Graphics USING [Box, Context, DrawBox, GetBounds, SetColor], GraphicsBasic USING [Color], GraphicsColor USING [RGBToColor, red, green, blue], IO USING [PutFR, real], Menus USING [Menu], MessageWindow USING [Append], Real USING [ReadReal], Rope USING [Equal, Fetch, Length, ROPE], Sliders USING [Create, SetContents, SliderProc, sliderGray], UserExec USING [CommandProc, RegisterCommand], VFonts USING [CharWidth], ViewerClasses USING [Column, PaintProc, Viewer, ViewerClass, ViewerClassRec], ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass, SetOpenHeight ], ViewerTools USING [MakeNewTextViewer, GetContents, SetContents], WindowManager USING [colorDisplayOn, ScreenPos, StartColorViewers, StopColorViewers]; ColorToolViewerImpl: CEDAR PROGRAM IMPORTS Buttons, NewCGColor, ChoiceButtons, CNSColor, ColorMap, Containers, Graphics, GraphicsColor, IO, MessageWindow, Real, Rope, Sliders, UserExec, VFonts, ViewerOps, ViewerTools, WindowManager EXPORTS ColorToolViewer = BEGIN entryHeight: CARDINAL = 15; -- how tall to make each line of text items entryVSpace: CARDINAL = 8; -- vertical leading space between lines entryHSpace: CARDINAL = 10; -- horizontal space between items in a line columnSpacing: INTEGER = 20; -- space between columns sliderWidth: CARDINAL = 20; -- width of all sliders in color tool sliderHeight: CARDINAL = 102; -- height of all sliders in color tool initialRed: REAL = 0.75; -- initial color values for color patch initialGreen: REAL = 0.75; initialBlue: REAL = 0.2; lastHandle: Handle _ NIL; --so the viewer can be manipulated by a program Handle: TYPE = REF ColorToolRec; ColorToolRec: TYPE = RECORD [ outer: Containers.Container _ NIL, -- handle for the enclosing container height: CARDINAL _ 0, -- height measured from the top of the container height2: CARDINAL _ 0, -- height of second column from top of the container rgb: RGBViewer, -- the RGB viewer's state hsv: HSVViewer, -- the HSV viewer's state hsl: HSLViewer, -- the HSL viewer's state cns: CNSViewer, -- the CNS viewer's state colorPatch: ColorPatchViewer -- the color patch viewer's state ]; Side: WindowManager.ScreenPos = left; GetRGBValue: PUBLIC PROC RETURNS [red,green,blue: REAL] = { data: ColorPatchData _ NARROW[lastHandle.colorPatch.data]; RETURN[red: data.rgbR, green: data.rgbG, blue: data.rgbB]; }; GetCSLValue: PUBLIC PROC RETURNS[cslChroma: CNSColor.CSLChroma, cslSaturation: CNSColor.CSLSaturation, cslLightness: CNSColor.CSLLightness] = { data: ColorPatchData _ NARROW[lastHandle.colorPatch.data]; RETURN[cslChroma: data.cslC, cslSaturation: data.cslS, cslLightness: data.cslL]; }; SetRGBValue: PUBLIC PROC [red,green,blue: REAL] = { UpdateColorViewers[handle: lastHandle, color: [rgb[red,green,blue]]]; }; SetCSLValue: PUBLIC PROC [cslChroma: CNSColor.CSLChroma, cslSaturation: CNSColor.CSLSaturation, cslLightness: CNSColor.CSLLightness] = { UpdateColorViewers[handle: lastHandle, color: [csl[cslChroma, cslSaturation, cslLightness]]]; }; MakeColorTool: UserExec.CommandProc = { my: Handle _ NEW[ColorToolRec]; column: ViewerClasses.Column _ color; IF WindowManager.colorDisplayOn = FALSE THEN column _ left; my.outer _ Containers.Create[ [ name: "Color Tool", iconic: FALSE, column: column, scrollable: FALSE ] ]; MakeRGB[my]; MakeHSV[my]; MakeHSL[my]; MakeCNS[my]; MakeColorPatch[my]; MakeOnOffButtons[my]; ViewerOps.SetOpenHeight[my.outer, my.height]; UpdateColorViewers[handle: my, color: [rgb[initialRed, initialGreen, initialBlue]]]; lastHandle _ my; }; RGBViewer: TYPE = RECORD [ redText: ViewerClasses.Viewer _ NIL, greenText: ViewerClasses.Viewer _ NIL, blueText: ViewerClasses.Viewer _ NIL, redSlider: ViewerClasses.Viewer _ NIL, greenSlider: ViewerClasses.Viewer _ NIL, blueSlider: ViewerClasses.Viewer _ NIL ]; MakeRGB: PROCEDURE [handle: Handle] = { [handle.rgb.redText, handle.rgb.greenText, handle.rgb.blueText, handle.rgb.redSlider, handle.rgb.greenSlider, handle.rgb.blueSlider] _ MakeColorSchemeViewer[ handle: handle, name: "RGB", buttonProc: ComputeFromRGB, sliderProc1: RedSliderUpdate, sliderProc2: GreenSliderUpdate, sliderProc3: BlueSliderUpdate, color1: GraphicsColor.red, color2: GraphicsColor.green, color3: GraphicsColor.blue ]; }; HSVViewer: TYPE = RECORD [ hueText: ViewerClasses.Viewer _ NIL, saturationText: ViewerClasses.Viewer _ NIL, valueText: ViewerClasses.Viewer _ NIL, hueSlider: ViewerClasses.Viewer _ NIL, saturationSlider: ViewerClasses.Viewer _ NIL, valueSlider: ViewerClasses.Viewer _ NIL ]; MakeHSV: PROCEDURE [handle: Handle] = { [handle.hsv.hueText, handle.hsv.saturationText, handle.hsv.valueText, handle.hsv.hueSlider, handle.hsv.saturationSlider, handle.hsv.valueSlider] _ MakeColorSchemeViewer[ handle: handle, name: "HSV", buttonProc: ComputeFromHSV, sliderProc1: HueSliderUpdate, sliderProc2: SaturationSliderUpdate, sliderProc3: ValueSliderUpdate ]; }; HSLViewer: TYPE = RECORD [ hueText: ViewerClasses.Viewer _ NIL, saturationText: ViewerClasses.Viewer _ NIL, lightnessText: ViewerClasses.Viewer _ NIL, hueSlider: ViewerClasses.Viewer _ NIL, saturationSlider: ViewerClasses.Viewer _ NIL, lightnessSlider: ViewerClasses.Viewer _ NIL ]; MakeHSL: PROCEDURE [handle: Handle] = { [handle.hsl.hueText, handle.hsl.saturationText, handle.hsl.lightnessText, handle.hsl.hueSlider, handle.hsl.saturationSlider, handle.hsl.lightnessSlider] _ MakeColorSchemeViewer[ handle: handle, name: "HSL", buttonProc: ComputeFromHSL, sliderProc1: HSLHueSliderUpdate, sliderProc2: HSLSaturationSliderUpdate, sliderProc3: HSLLightnessSliderUpdate ]; }; MakeColorSchemeViewer: PROCEDURE [handle: Handle, name: Rope.ROPE, buttonProc: Buttons.ButtonProc, sliderProc1, sliderProc2, sliderProc3: Sliders.SliderProc, color1, color2, color3: GraphicsBasic.Color _ Sliders.sliderGray] RETURNS [text1, text2, text3, slider1, slider2, slider3: ViewerClasses.Viewer] = { valueEntryWidth: CARDINAL = 8 * VFonts.CharWidth['0]; -- eight digits worth of width button: Buttons.Button; handle.height _ handle.height + entryVSpace; button _ Buttons.Create[ info: [ name: name, wy: handle.height, wh: entryHeight, parent: handle.outer, border: TRUE ], clientData: handle, proc: buttonProc ]; text1 _ ViewerTools.MakeNewTextViewer[ [ parent: handle.outer, wx: button.wx + button.ww + entryHSpace, wy: handle.height+2, ww: valueEntryWidth, wh: entryHeight, data: " ", scrollable: FALSE, border: FALSE ] ]; text2 _ ViewerTools.MakeNewTextViewer[ [ parent: handle.outer, wx: text1.wx + text1.ww + entryHSpace, wy: handle.height+2, ww: valueEntryWidth, wh: entryHeight, data: " ", scrollable: FALSE, border: FALSE ] ]; text3 _ ViewerTools.MakeNewTextViewer[ [ parent: handle.outer, wx: text2.wx + text2.ww + entryHSpace, wy: handle.height+2, ww: valueEntryWidth, wh: entryHeight, data: " ", scrollable: FALSE, border: FALSE ] ]; handle.height _ handle.height + entryHeight + entryVSpace; slider1 _ Sliders.Create[ info: [ parent: handle.outer, wx: button.wx + button.ww + entryHSpace, wy: handle.height, ww: sliderWidth, wh: sliderHeight ], foreground: color1, clientData: handle, sliderProc: sliderProc1 ]; slider2 _ Sliders.Create[ info: [ parent: handle.outer, wx: text1.wx + text1.ww + entryHSpace, wy: handle.height, ww: sliderWidth, wh: sliderHeight ], foreground: color2, clientData: handle, sliderProc: sliderProc2 ]; slider3 _ Sliders.Create[ info: [ parent: handle.outer, wx: text2.wx + text2.ww + entryHSpace, wy: handle.height, ww: sliderWidth, wh: sliderHeight ], foreground: color3, clientData: handle, sliderProc: sliderProc3 ]; handle.height _ handle.height + sliderHeight + entryVSpace; RETURN[text1, text2, text3, slider1, slider2, slider3]; }; CNSHues: ChoiceButtons.ButtonList _ LIST[ "Red", "OrangishRed", "RedOrange", "ReddishOrange", "Orange", "YellowishOrange", "OrangeYellow", "OrangishYellow", "Yellow", "GreenishYellow", "YellowGreen", "YellowishGreen", "Green", "BluishGreen", "GreenBlue", "GreenishBlue", "Blue", "PurplishBlue", "BluePurple", "BluishPurple", "Purple", "ReddishPurple", "PurpleRed", "PurplishRed", "BrownishRed", "RedBrown", "ReddishBrown", "Brown", "YellowishBrown", "BrownYellow", "BrownishYellow", "Black", "Gray", "White" ]; CNSLightnesses: ChoiceButtons.ButtonList _ LIST[ "VeryDark", "Dark", "Medium", "Light", "VeryLight" ]; CNSSaturations: ChoiceButtons.ButtonList _ LIST[ "Grayish", "Moderate", "Strong", "Vivid" ]; CNSViewer: TYPE = RECORD [ saturationChoices: ChoiceButtons.EnumTypeRef, lightnessChoices: ChoiceButtons.EnumTypeRef, hueChoices: ChoiceButtons.EnumTypeRef ]; MakeCNS: PROCEDURE [handle: Handle] = { maxWidth: CARDINAL = 625; button: Buttons.Button; handle.height2 _ handle.height2 + entryVSpace; button _ Buttons.Create[ info: [ name: "CNS", wx: handle.rgb.blueText.wx + handle.rgb.blueText.ww + columnSpacing, wy: handle.height2, wh: entryHeight, parent: handle.outer, border: TRUE ], clientData: handle, proc: ComputeFromCNS ]; handle.cns.saturationChoices _ ChoiceButtons.BuildEnumTypeSelection[ viewer: handle.outer, x: button.wx + button.ww + entryHSpace, y: handle.height2, title: "Saturation:", buttonNames: CNSSaturations, default: "Vivid", borderOnButtons: FALSE, notifyClientProc: CNSSaturationUpdate, clientdata: handle, style: menuSelection, allInOneRow: TRUE ]; handle.height2 _ handle.height2 + entryHeight; handle.cns.lightnessChoices _ ChoiceButtons.BuildEnumTypeSelection[ viewer: handle.outer, x: button.wx + button.ww + entryHSpace, y: handle.height2, title: "Lightness:", buttonNames: CNSLightnesses, default: "Medium", borderOnButtons: FALSE, notifyClientProc: CNSLightnessUpdate, clientdata: handle, style: menuSelection, allInOneRow: TRUE ]; handle.height2 _ handle.height2 + entryHeight; handle.cns.hueChoices _ ChoiceButtons.BuildEnumTypeSelection[ viewer: handle.outer, x: button.wx + button.ww + entryHSpace, y: handle.height2, title: "Hue:", buttonNames: CNSHues, borderOnButtons: FALSE, notifyClientProc: CNSHueUpdate, clientdata: handle, style: menuSelection, allInOneRow: FALSE, maxWidth: maxWidth ]; handle.height2 _ handle.height2 + 8*entryHeight + entryVSpace; }; ColorPatchViewer: TYPE = RECORD [viewer: ViewerClasses.Viewer _ NIL]; ColorPatchData: TYPE = REF ColorPatchDataRec; ColorPatchDataRec: TYPE = RECORD [ index: CARDINAL _ 51, -- color map index rgbR: REAL _ 1.0, rgbG: REAL _ 1.0, rgbB: REAL _ 0.0, hsvH: REAL _ 0.0, hsvS: REAL _ 0.0, hsvV: REAL _ 0.0, hslH: REAL _ 0.0, hslS: REAL _ 0.0, hslL: REAL _ 0.0, cslC: CNSColor.CSLChroma _ CNSColor.red, cslS: CNSColor.CSLSaturation _ CNSColor.vivid, cslL: CNSColor.CSLLightness _ CNSColor.medium ]; MakeColorPatch: PROCEDURE [handle: Handle] = { width: INTEGER = 100; height: INTEGER = 100; instanceData: ColorPatchData _ NEW[ColorPatchDataRec]; handle.height2 _ handle.height2 + entryVSpace; handle.colorPatch.viewer _ ViewerOps.CreateViewer[ flavor: $ColorPatch, info: [ parent: handle.outer, wx: handle.rgb.blueText.wx + handle.rgb.blueText.ww + columnSpacing, wy: handle.height2, ww: width, wh: height, data: instanceData, scrollable: FALSE] ]; handle.height2 _ handle.height2 + height + entryVSpace; }; PaintColorPatch: ViewerClasses.PaintProc = { box: Graphics.Box _ Graphics.GetBounds[context]; patchData: ColorPatchData _ NARROW[self.data]; color: GraphicsBasic.Color _ GraphicsColor.RGBToColor[r: patchData.rgbR, g: patchData.rgbG, b: patchData.rgbB]; ColorMap.SetRGBColor[index: patchData.index, r: patchData.rgbR, g: patchData.rgbG, b: patchData.rgbB]; Graphics.SetColor[context, color]; Graphics.DrawBox[context, box]; }; MakeOnOffButtons: PROCEDURE [handle: Handle] = { onButton, offButton: Buttons.Button; handle.height _ handle.height + entryVSpace; onButton _ Buttons.Create[ info: [ name: "Color On", wy: handle.height, wh: entryHeight, parent: handle.outer, border: TRUE ], clientData: handle, proc: TurnOnColorDisplay ]; offButton _ Buttons.Create[ info: [ name: "Color Off", wy: handle.height, wx: onButton.wx + onButton.ww + entryHSpace, wh: entryHeight, parent: handle.outer, border: TRUE ], clientData: handle, proc: TurnOffColorDisplay ]; handle.height _ handle.height + entryHeight + entryVSpace; }; TurnOnColorDisplay: Buttons.ButtonProc = { IF WindowManager.colorDisplayOn = FALSE THEN WindowManager.StartColorViewers[screenPos: Side, bitsPerPixel: 8]; }; TurnOffColorDisplay: Buttons.ButtonProc = { WindowManager.StopColorViewers[]; }; ComputeFromRGB: Buttons.ButtonProc = { handle: Handle _ NARROW[clientData]; redValue: REAL _ GetColorValue[ViewerTools.GetContents[handle.rgb.redText]]; greenValue: REAL _ GetColorValue[ViewerTools.GetContents[handle.rgb.greenText]]; blueValue: REAL _ GetColorValue[ViewerTools.GetContents[handle.rgb.blueText]]; UpdateColorViewers[handle: handle, color: [rgb[redValue, greenValue, blueValue]]]; }; RedSliderUpdate: Sliders.SliderProc = { handle: Handle _ NARROW[clientData]; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; UpdateColorViewers[handle: handle, color: [rgb[value, patchData.rgbG, patchData.rgbB]]]; }; GreenSliderUpdate: Sliders.SliderProc = { handle: Handle _ NARROW[clientData]; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; UpdateColorViewers[handle: handle, color: [rgb[patchData.rgbR, value, patchData.rgbB]]]; }; BlueSliderUpdate: Sliders.SliderProc = { handle: Handle _ NARROW[clientData]; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; UpdateColorViewers[handle: handle, color: [rgb[patchData.rgbR, patchData.rgbG, value]]]; }; ComputeFromHSV: Buttons.ButtonProc = { handle: Handle _ NARROW[clientData]; hueContents: Rope.ROPE _ ViewerTools.GetContents[handle.hsv.hueText]; saturationContents: Rope.ROPE _ ViewerTools.GetContents[handle.hsv.saturationText]; valueContents: Rope.ROPE _ ViewerTools.GetContents[handle.hsv.valueText]; hueValue: REAL _ GetColorValue[hueContents]; saturationValue: REAL _ GetColorValue[saturationContents]; valueValue: REAL _ GetColorValue[valueContents]; UpdateColorViewers[handle: handle, color: [hsv[hueValue, saturationValue, valueValue]]]; }; HueSliderUpdate: Sliders.SliderProc = { handle: Handle _ NARROW[clientData]; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; UpdateColorViewers[handle: handle, color: [hsv[value, patchData.hsvS, patchData.hsvV]]]; }; SaturationSliderUpdate: Sliders.SliderProc = { handle: Handle _ NARROW[clientData]; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; UpdateColorViewers[handle: handle, color: [hsv[patchData.hsvH, value, patchData.hsvV]]]; }; ValueSliderUpdate: Sliders.SliderProc = { handle: Handle _ NARROW[clientData]; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; UpdateColorViewers[handle: handle, color: [hsv[patchData.hsvH, patchData.hsvS, value]]]; }; ComputeFromHSL: Buttons.ButtonProc = { handle: Handle _ NARROW[clientData]; hueContents: Rope.ROPE _ ViewerTools.GetContents[handle.hsl.hueText]; saturationContents: Rope.ROPE _ ViewerTools.GetContents[handle.hsl.saturationText]; lightnessContents: Rope.ROPE _ ViewerTools.GetContents[handle.hsl.lightnessText]; hueValue: REAL _ GetColorValue[hueContents]; saturationValue: REAL _ GetColorValue[saturationContents]; lightnessValue: REAL _ GetColorValue[lightnessContents]; UpdateColorViewers[handle: handle, color: [hsv[hueValue, saturationValue, lightnessValue]]]; }; HSLHueSliderUpdate: Sliders.SliderProc = { handle: Handle _ NARROW[clientData]; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; UpdateColorViewers[handle: handle, color: [hsl[value, patchData.hslS, patchData.hslL]]]; }; HSLSaturationSliderUpdate: Sliders.SliderProc = { handle: Handle _ NARROW[clientData]; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; UpdateColorViewers[handle: handle, color: [hsl[patchData.hslH, value, patchData.hslL]]]; }; HSLLightnessSliderUpdate: Sliders.SliderProc = { handle: Handle _ NARROW[clientData]; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; UpdateColorViewers[handle: handle, color: [hsl[patchData.hslH, patchData.hslS, value]]]; }; GetColorValue: PROCEDURE [rope: Rope.ROPE] RETURNS [value: REAL] = { value _ ConvertRopeToReal[rope]; IF value > 1.0 OR value < 0.0 THEN { MessageWindow.Append[message: "Invalid value ", clearFirst: TRUE]; MessageWindow.Append[message: rope, clearFirst: FALSE]; value _ 1.0; }; RETURN[value]; }; ComputeFromCNS: Buttons.ButtonProc = { handle: Handle _ NARROW[clientData]; c: CNSColor.CSLChroma; s: CNSColor.CSLSaturation; l: CNSColor.CSLLightness; hue: Rope.ROPE _ ChoiceButtons.GetSelectedButton[handle.cns.hueChoices]; saturation: Rope.ROPE _ ChoiceButtons.GetSelectedButton[handle.cns.saturationChoices]; lightness: Rope.ROPE _ ChoiceButtons.GetSelectedButton[handle.cns.lightnessChoices]; [c, s, l] _ CNSColor.CNSToCSL[hue, saturation, lightness]; UpdateColorViewers[handle: handle, color: [csl[c, s, l]]]; }; CNSHueUpdate: ChoiceButtons.SelectionNotifierProc = { handle: Handle _ NARROW[clientdata]; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; hue, saturation, lightness: Rope.ROPE; c: CNSColor.CSLChroma; s: CNSColor.CSLSaturation; l: CNSColor.CSLLightness; [hue, saturation, lightness] _ CNSColor.CSLToCNS[patchData.cslC, patchData.cslS, patchData.cslL]; [c, s, l] _ CNSColor.CNSToCSL[ name, saturation, lightness]; UpdateColorViewers[handle: handle, color: [csl[c, s, l]]]; }; CNSSaturationUpdate: ChoiceButtons.SelectionNotifierProc = { handle: Handle _ NARROW[clientdata]; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; hue, saturation, lightness: Rope.ROPE; c: CNSColor.CSLChroma; s: CNSColor.CSLSaturation; l: CNSColor.CSLLightness; [hue, saturation, lightness] _ CNSColor.CSLToCNS[patchData.cslC, patchData.cslS, patchData.cslL]; [c, s, l] _ CNSColor.CNSToCSL[ hue, name, lightness]; UpdateColorViewers[handle: handle, color: [csl[c, s, l]]]; }; CNSLightnessUpdate: ChoiceButtons.SelectionNotifierProc = { handle: Handle _ NARROW[clientdata]; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; hue, saturation, lightness: Rope.ROPE; c: CNSColor.CSLChroma; s: CNSColor.CSLSaturation; l: CNSColor.CSLLightness; [hue, saturation, lightness] _ CNSColor.CSLToCNS[patchData.cslC, patchData.cslS, patchData.cslL]; [c, s, l] _ CNSColor.CNSToCSL[ hue, saturation, name]; UpdateColorViewers[handle: handle, color: [csl[c, s, l]]]; }; ColorSpecification: TYPE = RECORD [ color: SELECT type: ColorType FROM hsv => [h, s, v: REAL], hsl => [h, s, l: REAL], rgb => [r, g, b: REAL], csl => [c: CNSColor.CSLChroma, s: CNSColor.CSLSaturation, l: CNSColor.CSLLightness], ENDCASE ]; ColorType: TYPE = {hsv, rgb, csl, hsl}; UpdateColorViewers: PROCEDURE [handle: Handle, color: ColorSpecification] RETURNS [] = { UpdateColorValue: PROCEDURE [oldValue, newValue: REAL, textViewer, sliderViewer: ViewerClasses.Viewer] RETURNS [new: REAL] = { IF newValue=NewCGColor.undefined THEN RETURN[oldValue]; IF newValue # oldValue THEN { ViewerTools.SetContents[viewer: textViewer, contents: IO.PutFR["%-5f", IO.real[newValue]]]; Sliders.SetContents[slider: sliderViewer, contents: newValue]; }; RETURN[newValue]; }; patchData: ColorPatchData _ NARROW[handle.colorPatch.viewer.data]; h, s, v: REAL; r, g, b: REAL; hl,sl,l: REAL; chroma: CNSColor.CSLChroma; saturation: CNSColor.CSLSaturation; lightness: CNSColor.CSLLightness; cnsHue, cnsSaturation, cnsLightness: Rope.ROPE; WITH col: color SELECT FROM hsv => { h _ col.h; s _ col.s; v _ col.v; [r, g, b] _ NewCGColor.HSVToRGB[h, s, v]; [hl, sl, l] _ NewCGColor.RGBToHSL[r, g, b]; [chroma, saturation, lightness] _ CNSColor.HSLToCSL[hl, sl, l]; }; hsl => { hl _ col.h; sl _ col.s; l _ col.l; [r, g, b] _ NewCGColor.HSLToRGB[hl, sl, l]; [h, s, v] _ NewCGColor.RGBToHSV[r, g, b]; [chroma, saturation, lightness] _ CNSColor.HSLToCSL[hl, sl, l]; }; rgb => { r _ col.r; g _ col.g; b _ col.b; [h, s, v] _ NewCGColor.RGBToHSV[ r, g, b ]; [hl, sl, l] _ NewCGColor.RGBToHSL[r, g, b]; [chroma, saturation, lightness] _ CNSColor.HSLToCSL[hl, sl, l]; }; csl => { chroma _ col.c; saturation _ col.s; lightness _ col.l; [hl, sl, l] _ CNSColor.CSLToHSL[ chroma, saturation, lightness]; [r, g, b] _ NewCGColor.HSLToRGB[hl, sl, l]; [h, s, v] _ NewCGColor.RGBToHSV[r, g, b]; } ENDCASE; patchData.rgbR _ UpdateColorValue[oldValue: patchData.rgbR, newValue: r, textViewer: handle.rgb.redText, sliderViewer: handle.rgb.redSlider]; patchData.rgbG _ UpdateColorValue[oldValue: patchData.rgbG, newValue: g, textViewer: handle.rgb.greenText, sliderViewer: handle.rgb.greenSlider]; patchData.rgbB _ UpdateColorValue[oldValue: patchData.rgbB, newValue: b, textViewer: handle.rgb.blueText, sliderViewer: handle.rgb.blueSlider]; patchData.hsvH _ UpdateColorValue[oldValue: patchData.hsvH, newValue: h, textViewer: handle.hsv.hueText, sliderViewer: handle.hsv.hueSlider]; patchData.hsvS _ UpdateColorValue[oldValue: patchData.hsvS, newValue: s, textViewer: handle.hsv.saturationText, sliderViewer: handle.hsv.saturationSlider]; patchData.hsvV _ UpdateColorValue[oldValue: patchData.hsvV, newValue: v, textViewer: handle.hsv.valueText, sliderViewer: handle.hsv.valueSlider]; patchData.hslH _ UpdateColorValue[oldValue: patchData.hslH, newValue: hl, textViewer: handle.hsl.hueText, sliderViewer: handle.hsl.hueSlider]; patchData.hslS _ UpdateColorValue[oldValue: patchData.hslS, newValue: sl, textViewer: handle.hsl.saturationText, sliderViewer: handle.hsl.saturationSlider]; patchData.hslL _ UpdateColorValue[oldValue: patchData.hslL, newValue: l, textViewer: handle.hsl.lightnessText, sliderViewer: handle.hsl.lightnessSlider]; [cnsHue, cnsSaturation, cnsLightness] _ CNSColor.CSLToCNS[chroma, saturation, lightness]; IF patchData.cslC # chroma AND ~Rope.Equal[cnsHue, ""] THEN { patchData.cslC _ chroma; ChoiceButtons.UpdateChoiceButtons[viewer: handle.outer, enumTypeInfo: handle.cns.hueChoices, newName: cnsHue]; }; IF patchData.cslS # saturation AND ~Rope.Equal[cnsSaturation, ""] THEN { patchData.cslS _ saturation; ChoiceButtons.UpdateChoiceButtons[viewer: handle.outer, enumTypeInfo: handle.cns.saturationChoices, newName: cnsSaturation]; }; IF patchData.cslL # lightness AND ~Rope.Equal[cnsLightness, ""] THEN { patchData.cslL _ lightness; ChoiceButtons.UpdateChoiceButtons[viewer: handle.outer, enumTypeInfo: handle.cns.lightnessChoices, newName: cnsLightness]; }; ViewerOps.PaintViewer[viewer: handle.colorPatch.viewer, hint: client, clearClient: FALSE]; }; ConvertRopeToReal: PROCEDURE [rope: Rope.ROPE] RETURNS [value: REAL] = { i : INT _ 0; Get: PROCEDURE RETURNS [c: CHARACTER] = { c _ IF i >= rope.Length THEN ' ELSE rope.Fetch[i]; i _ i + 1; RETURN[c]; }; RETURN[Real.ReadReal[Get]]; }; colorPatchClass: ViewerClasses.ViewerClass _ NEW[ViewerClasses.ViewerClassRec _ [paint: PaintColorPatch]]; UserExec.RegisterCommand[name: "ColorTool", proc: MakeColorTool, briefDoc: "Create a color tool" ]; ViewerOps.RegisterViewerClass[$ColorPatch, colorPatchClass]; IF WindowManager.colorDisplayOn = FALSE THEN WindowManager.StartColorViewers[screenPos: Side, bitsPerPixel: 8]; ColorMap.SetRGBColor[index: 1, r: 1.0, g: 1.0, b: 1.0]; [ ] _ MakeColorTool[NIL, NIL]; -- and create an instance END. šColorToolViewerImpl.mesa Written by Darlene Plebon on August 30, 1983 5:28 pm Last Edited by: Stone, July 8, 1983 11:59 am The following procedure gets a compiler warning: long REF-containing arg/return record is unsafe, at MakeColorSchemeViewer. Nothing has been done about it as everything seems to work! The color naming scheme. The color patch reflecting the currently selected color. colorPatchClass is a record containing the procedures and data common to all ColorPatch viewer instances (class record). Register a command with the UserExec that will create an instance of this tool. Register the ColorPatch class of viewer with the Window Manager Κk– "Cedar" style˜Iproc– "Cedar" stylešœ™K– "Cedar" stylešœ4™4J™,unitšΟk ˜ Lšœ˜Jšœœ˜+Jšœ œ5˜EJšœœr˜…Jšœ œf˜tJšœ œ˜Jšœ œ˜%Jšœ œ.˜˜>J˜—J˜Jšœ8™8Jšœœœ!œ˜EJšœœœ˜.šœœœ˜"Jšœœž˜)Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœ(˜(Jšœ.˜.Jšœ-˜-Jšœ˜—J˜šŸœ œ˜.Jšœœ˜Jšœœ˜Jšœœ˜6Jšœ.˜.šœ2˜2Jšœ˜šœ˜Jšœ˜JšœD˜DJšœ˜Jšœ ˜ Jšœ ˜ J˜Jšœ œ˜—Jšœ˜—Jšœ7˜7Jšœ˜—J˜šŸœ˜,J˜0Kšœœ ˜.Kšœo˜oK•StartOfExpansion8[index: CARDINAL _ 0, r: REAL, g: REAL, b: REAL]šœf˜fKšœ"˜"Kšœ ˜ Jšœ˜—J˜šŸœ œ˜0Jšœ$˜$Jšœ,˜,šœ˜šœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœœ˜—Jšœ˜Jšœ˜—šœ˜šœ˜Jšœ˜Jšœ˜Jšœ,˜,Jšœ˜Jšœ˜Jšœœ˜—Jšœ˜Jšœ˜—Jšœ:˜:Jšœ˜J˜—šŸœ˜*šœ  ˜,MšœB˜B—J˜J˜—šŸœ˜+Jšœ!˜!J˜J˜—šŸœ˜&Jšœœ ˜$Jšœ œ>˜LJšœ œ@˜PJšœ œ?˜NJšœR˜RJšœ˜—J˜šŸœ˜'Jšœœ ˜$Kšœœ ˜BJšœX˜XJšœ˜—J˜šŸœ˜)Jšœœ ˜$Kšœœ ˜BJšœX˜XJšœ˜—J˜šŸœ˜(Jšœœ ˜$Kšœœ ˜BJšœX˜XJšœ˜—J˜šŸœ˜&Jšœœ ˜$Jšœœ/˜EJšœœ6˜SJšœœ1˜IJšœ œ˜,Jšœœ%˜:Jšœ œ ˜0JšœX˜XJšœ˜—J˜šŸœ˜'Jšœœ ˜$Kšœœ ˜BJšœX˜XJšœ˜—J˜šŸœ˜.Jšœœ ˜$Kšœœ ˜BJšœX˜XJšœ˜—J˜šŸœ˜)Jšœœ ˜$Kšœœ ˜BJšœX˜XJšœ˜—J˜šŸœ˜&Jšœœ ˜$Jšœœ/˜EJšœœ6˜SJšœœ5˜QJšœ œ˜,Jšœœ%˜:Jšœœ$˜8Jšœ\˜\Jšœ˜—J˜šŸœ˜*Jšœœ ˜$Kšœœ ˜BJšœX˜XJšœ˜—J˜šŸœ˜1Jšœœ ˜$Kšœœ ˜BJšœX˜XJšœ˜—J˜šŸœ˜0Jšœœ ˜$Kšœœ ˜BJšœX˜XJšœ˜—š Ÿ œ œ œœ œ˜DJ˜ šœ œ œ˜$Jšœ<œ˜BJšœ0œ˜7J˜ Jšœ˜—Jšœ˜J˜—J˜šŸœ˜&Jšœœ ˜$Jšœ˜Jšœ˜Jšœ˜Jšœ œ:˜HJšœœA˜VJšœœ@˜TJšœ:˜:Jšœ:˜:J˜—J™šŸ œ)˜5Jšœœ ˜$Kšœœ ˜BJšœ!œ˜&Jšœ˜Jšœ˜Jšœ˜Jšœa˜aJšœ<˜˜>Jšœ˜—Jšœ ˜J˜—Kšœœ ˜BKšœ œ˜Kšœ œ˜Kšœ œ˜Jšœ˜Jšœ#˜#Jšœ!˜!Kšœ*œ˜/šœ œ˜šœ˜Jšœ ˜ Jšœ)˜)Jšœ+˜+Jšœ?˜?Jšœ˜—šœ˜Jšœ"˜"Jšœ+˜+Jšœ)˜)Jšœ?˜?Jšœ˜—šœ˜Jšœ ˜ Jšœ+˜+Jšœ+˜+Jšœ?˜?J˜—šœ˜Jšœ6˜6Jšœ@˜@Jšœ+˜+Jšœ)˜)J˜—Jšœ˜—JšœŽ˜ŽJšœ’˜’Jšœ˜JšœŽ˜ŽJšœœ˜œJšœ’˜’Jšœ˜Jšœ˜Jšœš˜šJšœY˜Yšœœœ˜=Jšœ˜Jšœn˜nJ˜—šœœ œ˜HJšœ˜Jšœ|˜|J˜—šœœœ˜FJšœ˜Jšœz˜zJ˜—JšœSœ˜ZJ˜—M™š Ÿœ œ œœ œ˜HJšœœ˜ šŸœ œœ œ˜)Jšœœœœ˜3J˜ Jšœ˜ J˜—Jšœ˜J˜—M™Mšœx™xšœ-˜-Mšœ:˜=—K™KšœO™OJšœc˜cM™Mšœ?™?Jšœ<˜