# a3_app.py # Walker M. White (wmw2), Lillian Lee (LJL2), Steve Marschner (srm2) # Feb 22, 2013 """Main module for color transformation GUI application. The GUI contains two color panes. The user controls the color shown in the first color pane via either sliders or entering RGB values in the text-entry boxes and then clicking the button. When you have correctly implemented the functions required in A3, the second pane will show what the first-pane color looks like to someone with protanopia, a type of red-green color blindness. When you have correctly implemented the functions required in A3.2, the second pane will show the color that is the user-specified transformation of the color in the first pane. This module is an example of a Kivy application. It must be in the same folder as colormodel.kv. You must not change the name of that file.""" from kivy.app import App from kivy.lang import Builder from kivy.uix.widget import Widget from kivy.uix.boxlayout import BoxLayout from kivy.uix.anchorlayout import AnchorLayout from kivy.properties import NumericProperty, ReferenceListProperty, ListProperty, ObjectProperty from kivy.vector import Vector from kivy.factory import Factory from kivy.graphics import Color from kivy.graphics import Ellipse from kivy.config import Config import colormodel import a3 import sys # imported fo access to command-line args in sys.argv # default transformation matrix and its title # these should not be altered PROTANOPIA = [[0.56667, 0.43333, 0], [0.55833, 0.44167, 0], [0, 0.24167, 0.75833]] PROT_TITLE = "Red-green color-blindness (Protanopia)" class Separator(Widget): """Instances are used to space out widgets from one another""" pass class ColorPanel(BoxLayout): """Instances display a color and its complement""" foreground = ListProperty([1,0,0,1]) background = ListProperty([0,1,1,1]) text = ObjectProperty("") class ColorSlider(BoxLayout): """Instances implement a slider widget""" color = ListProperty([1,1,1,1]) slider = ObjectProperty(None) text = ObjectProperty("") group_id = ObjectProperty("") max_value = NumericProperty(1000) min_value = NumericProperty(0) initial = NumericProperty(10) @property def value(self): """Delegate to slider value.""" return self.slider.value @value.setter def value(self, value): self.slider.value = value @value.deleter def value(self): del self.slider.value def bind(self,**kw): """Bind to slider state; pass others to super""" if (kw.has_key("slide")): self.slider.bind(value=kw["slide"]) del kw["slide"] super(ColorSlider,self).bind(**kw) class TopPanel(BoxLayout): """Instances implement the top panel (sliders and color panels)""" main = ObjectProperty(None) comp = ObjectProperty(None) rSlider = ObjectProperty(None) gSlider = ObjectProperty(None) bSlider = ObjectProperty(None) matrix = ObjectProperty(None) def update(self, rgb): """Refresh the color and text display in the color panels""" compRGB = a3.complement_rgb(rgb) # this controls the font color if (compRGB is None): # student hasn't implemented yet compRGB = colormodel.BLACK # use black for font transformedRGB = a3.apply_matrix(self.matrix, rgb) if (transformedRGB is None): # student hasn't implemented yet transformedRGB = rgb rgb_str = str(rgb) transformed_str = str(transformedRGB) self.main.text = ("Color's RGB:\n" + rgb_str) self.main.background = rgb.glColor() self.main.foreground = compRGB.glColor() self.comp.text = "Transformed Color's RGB:\n" + transformed_str self.comp.background = transformedRGB.glColor() try: self.comp.foreground = a3.complement_rgb(transformedRGB).glColor() except: # student hasn't implemented complement_rgb yet self.comp.foreground = colormodel.BLACK.glColor() # set the slider self.rSlider.value = rgb.red*100 self.gSlider.value = rgb.green*100 self.bSlider.value = rgb.blue*100 class BotPanel(BoxLayout): """Instances implement the top panel (text boxes and buttons)""" rgbButton = ObjectProperty(None) cmykButton = ObjectProperty(None) hsvButton = ObjectProperty(None) rField = ObjectProperty(None) gField = ObjectProperty(None) bField = ObjectProperty(None) transformName = ObjectProperty("Blah") def _toInt(self,s): """Returns: if s is not an int, 0 else max(0, min(255, s).""" try: i = int(s) return i except ValueError: return 0 def clear(self): self.rField.text = "" self.gField.text = "" self.bField.text = "" class ColorWidget(BoxLayout): """Instances represent the top level widget""" active = True rgb = colormodel.RGB(0, 255, 0) top = ObjectProperty(None) bot = ObjectProperty(None) def __init__(self, transformName, matrix): BoxLayout.__init__(self) self.transformName = transformName self.matrix = matrix def register(self): """Initialize color values and force refresh""" self.rgb = colormodel.RGB(179, 27, 27) self.bot.transformName = self.transformName self.top.matrix = self.matrix self.bot._trigger_layout() self.update() def update(self): """Force refresh of top panel on update""" self.active = False self.top.update(self.rgb) self.active = True def on_rgb_press(self,r,g,b): """Call back to rgb button""" self.bot.clear() self.rgb = colormodel.RGB(r, g, b) self.update() def on_rgb_slide(self,r,g,b): """Call back to rgb sliders""" if not self.active: return red = int(round(r / 100.0)) green = int(round(g / 100.0)) blue = int(round(b / 100.0)) self.rgb = colormodel.RGB(red, green, blue) self.update() class ColorModelApp(App): """An Instance is the color-transformation application.""" def __init__(self, transformName, matrix): App.__init__(self) self.transformName = transformName self.matrix = matrix def build(self): """Read kivy file and perform layout""" Config.set('graphics', 'width', '1150') Config.set('graphics', 'height', '300') return ColorWidget(self.transformName, self.matrix) def on_start(self): """Start up the app and initialize values""" super(ColorModelApp,self).on_start() self.root.register() print dir(self) Factory.register("Separator", Separator) Factory.register("ColorPanel", ColorPanel) Factory.register("ColorSlider", ColorSlider) Factory.register("TopPanel", TopPanel) Factory.register("BotPanel", BotPanel) # Application Code if __name__ in ('__android__', '__main__'): try: (title, the_matrix) = a3.read_matrix(sys.argv[1]) except: # Use predefined default values print 'Using default transform (Protanopia)' title = PROT_TITLE the_matrix = PROTANOPIA ColorModelApp(title, the_matrix).run()