mansrz / pymt

Automatically exported from code.google.com/p/pymt
0 stars 0 forks source link

Extend MTInnerWindow to add aspect ratio controls #246

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Enhance the MTInnerWindow with controls for changing the aspect ratio of
the window just like any OS window works.

My first attempt is shown below. It works except for when rotated and
altering the size from any aspect control other than that at the top right
of the window.

# PYMT Plugin integration
IS_PYMT_PLUGIN = True
PLUGIN_TITLE = 'Napier Browser'
PLUGIN_AUTHOR = 'Jay Bradley'
PLUGIN_DESCRIPTION = 'Browse through file and search web resources'

from pymt import *
import os
import random
from OpenGL.GL import *

current_dir = os.path.dirname(__file__)

class MTNapierInnerWindow(MTInnerWindow):
  def __init__(self, **kwargs):
    print "MTNapierInnerWindow constructed"
    kwargs.setdefault('scale_min', 0.5)
    kwargs.setdefault('scale_max', 2)
    self.height_max = 600
    self.height_min = 100
    self.width_max = 600
    self.width_min = 200
    self.grow_delta = Vector(0, 0)
    self.aspect_controls_touches = {}
    MTInnerWindow.__init__(self, **kwargs)
    self.add_hold_aspect_ratio_controls()

  def fullscreen(self, *largs, **kwargs):
    self.hide_hold_aspect_ratio_controls()

    root_win = self.parent.get_parent_window()
    parent_widget = self.parent

    # save state for restore
    self.old_children = parent_widget.children
    self.old_size = self.size

    # set new children
    parent_widget.children = SafeList()
    rotation_to_nearest_90 = int(round(self.rotation / 90, 0)) * 90

    self.orientation_widget = MTScatterWidget(size = root_win.size,
rotation = rotation_to_nearest_90) # round rotation to nearest compass point

    if(rotation_to_nearest_90 == 0 or rotation_to_nearest_90 == 360):
      self.size = self.orientation_widget.size
      self.container.size = self.size
    elif(rotation_to_nearest_90 == 90):
      self.orientation_widget.pos = (self.orientation_widget.pos[0] +
self.orientation_widget.width, self.orientation_widget.pos[1])
      self.orientation_widget.size = (self.orientation_widget.size[1],
self.orientation_widget.size[0]) # swap height and width because it's on
its side
      self.size = self.orientation_widget.size
      self.container.size = self.size
    elif(rotation_to_nearest_90 == 180):
      self.orientation_widget.pos = (self.orientation_widget.pos[0] +
self.orientation_widget.width, self.orientation_widget.pos[1] +
self.orientation_widget.height)
      self.size = self.orientation_widget.size
      self.container.size = self.size
    elif(rotation_to_nearest_90 == 270):
      self.orientation_widget.pos = (self.orientation_widget.pos[0],
self.orientation_widget.pos[1] + self.orientation_widget.height)
      self.orientation_widget.size = (self.orientation_widget.size[1],
self.orientation_widget.size[0]) # swap height and width because it's on
its side
      self.size = self.orientation_widget.size
      self.container.size = self.size

    parent_widget.add_widget(self.orientation_widget)
    self.orientation_widget.add_widget(self.container)

    btn_unfullscreen = MTButton(pos=(self.orientation_widget.width-50,
self.orientation_widget.height-50), size=(50,50), label='Back')
    btn_unfullscreen.push_handlers(on_release=self.unfullscreen)
    self.orientation_widget.add_widget(btn_unfullscreen)

  def unfullscreen(self, *largs, **kwargs):
    # restore old widget
    parent_widget = self.parent

    parent_widget.children = self.old_children

    # reset container parent
    self.container.parent = self

    # set old size
    self.size = self.old_size
    self.container.size = self.size    

    self.show_hold_aspect_ratio_controls()

  def add_hold_aspect_ratio_controls(self):
    scaled_border = self.get_scaled_border()

    self.aspect_controls = MTWidget()
    self.add_widget(self.aspect_controls) # not sure if this is needed.
Works without it.

    self.aspect_control_bottom_left = MTButton(pos=(-scaled_border,
-scaled_border), size = (scaled_border, scaled_border),
cls="aspect_ratio_controls")
    self.aspect_controls.add_widget(self.aspect_control_bottom_left)

    self.aspect_control_top_left = MTButton(pos=(-scaled_border,
self.height), size = (scaled_border, scaled_border),
cls="aspect_ratio_controls")
    self.aspect_controls.add_widget(self.aspect_control_top_left)

    self.aspect_control_bottom_right = MTButton(pos=(self.width,
-scaled_border), size = (scaled_border, scaled_border),
cls="aspect_ratio_controls")
    self.aspect_controls.add_widget(self.aspect_control_bottom_right)

    self.aspect_control_top_right = MTButton(pos=(self.width, self.height),
size = (scaled_border, scaled_border), cls="aspect_ratio_controls")
    self.aspect_controls.add_widget(self.aspect_control_top_right)

  def hide_hold_aspect_ratio_controls(self):
    self.aspect_controls.visible = False

  def show_hold_aspect_ratio_controls(self):
    self.aspect_controls.visible = True

  def update_aspect_controls(self):
    scaled_border = self.get_scaled_border()

    scale_of_aspect_controls = 0.8
    size_of_aspect_controls = scaled_border * scale_of_aspect_controls

    self.aspect_control_bottom_left.pos = (-scaled_border *
scale_of_aspect_controls, -scaled_border * scale_of_aspect_controls)
    self.aspect_control_bottom_left.size = (size_of_aspect_controls,
size_of_aspect_controls)

    self.aspect_control_top_left.pos = (-scaled_border *
scale_of_aspect_controls, self.height)
    self.aspect_control_top_left.size = (size_of_aspect_controls,
size_of_aspect_controls)

    self.aspect_control_bottom_right.pos = (self.width, -scaled_border *
scale_of_aspect_controls)
    self.aspect_control_bottom_right.size = (size_of_aspect_controls,
size_of_aspect_controls)

    self.aspect_control_top_right.pos = (self.width, self.height)
    self.aspect_control_top_right.size = (size_of_aspect_controls,
size_of_aspect_controls)

  def on_touch_down(self, touch):
    if(len(self.aspect_controls_touches.keys()) == 0): # only one touch
allowed at a time on the aspect ratio controls
      local_touch = self.to_local(touch.x, touch.y)
      if(self.aspect_control_bottom_left.collide_point(local_touch[0],
local_touch[1])):
        #print "MTNapierInnerWindow touch down over bottom left aspect control"
        self.aspect_controls_touches[touch.id] = ["bottom", "left"]
      elif(self.aspect_control_top_left.collide_point(local_touch[0],
local_touch[1])):
        #print "MTNapierInnerWindow touch down over top left aspect control"
        self.aspect_controls_touches[touch.id] = ["top", "left"]
      elif(self.aspect_control_bottom_right.collide_point(local_touch[0],
local_touch[1])):
        #print "MTNapierInnerWindow touch down over bottom right aspect
control"
        self.aspect_controls_touches[touch.id] = ["bottom", "right"]
      elif(self.aspect_control_top_right.collide_point(local_touch[0],
local_touch[1])):
        #print "MTNapierInnerWindow touch down over top right aspect control"
        self.aspect_controls_touches[touch.id] = ["top", "right"]
      #else:
        #'print "MTNapierInnerWindow touch down NOT over aspect controls"
    MTInnerWindow.on_touch_down(self, touch)

  def on_touch_up(self, touch):
    # if touch in self.aspect_controls_touches then remove it
    if(touch.id in self.aspect_controls_touches.keys()):
      del self.aspect_controls_touches[touch.id]
    MTInnerWindow.on_touch_up(self, touch)

  def apply_angle_scale_trans(self, angle, scale, trans, point=Vector(0, 0)):

    if(len(self.aspect_controls_touches.keys()) >= 1 and len(self.touches)
== 1):  # change size rather than scale

      grow_delta = Vector(trans.x, trans.y)
      grow_delta = grow_delta.rotate(360.0 - self.rotation)

      aspect_control_location = self.aspect_controls_touches.items()[0][1]

      # handle switch in direction of growth      
      # left
      if("left" in aspect_control_location):
        grow_delta[0] *= -1.0
      # bottom
      if("bottom" in aspect_control_location):
        grow_delta[1] *= -1.0

      # change the size
      self.width += grow_delta[0]
      self.height += grow_delta[1]  

      # offset the window
      trans.x = 0
      trans.y = 0
      # left
      if("left" in aspect_control_location):
        trans.x = -grow_delta[0]
      # bottom
      if("bottom" in aspect_control_location):
        trans.y = -grow_delta[1]

      # check that the widget isn't too small or too large
      if(self.height <= self.height_min):
        self.height = self.height_min
      elif(self.height >= self.height_max):
        self.height = self.height_max
      if(self.width <= self.width_min):
        self.width = self.width_min
      elif(self.width >= self.width_max):
        self.width = self.width_max

      # resize the widget's container too
      self.container.height = self.height
      self.container.width = self.width

      #invalidate cached values for parent transform calucaltion
      self.__to_local = (-9999, 9999)
      self.__to_parent = (-9999, 9999)
      self.dispatch_event('on_transform', angle, scale, trans, point)

      scale = 0
      rotate = 0

    #else:
      # apply the changes as normal if not changing the aspect ratio
    MTScatterWidget.apply_angle_scale_trans(self, angle, scale, trans, point)

  def draw(self):
    self.update_aspect_controls()
    MTInnerWindow.draw(self)
    self.aspect_controls.dispatch_event('on_draw')

Original issue reported on code.google.com by jaybradl...@gmail.com on 28 Apr 2010 at 10:06

GoogleCodeExporter commented 9 years ago

Original comment by txprog on 15 Aug 2010 at 11:35

GoogleCodeExporter commented 9 years ago

Original comment by txprog on 19 Aug 2010 at 11:38