2017-01-10 20:57:02 +00:00
|
|
|
--- A generic window element. Built-in support for minimize, maximize, and close
|
|
|
|
--- buttons, as well as drag-to-resize and drag-to-move. Title bar customizable.
|
2016-08-23 04:22:13 +00:00
|
|
|
--- @classmod window
|
|
|
|
--- @copyright Paul Liverman III (2016)
|
|
|
|
--- @license The MIT License (MIT)
|
2017-04-30 23:40:29 +00:00
|
|
|
--- @todo Implement missing features.
|
2016-08-23 04:22:13 +00:00
|
|
|
|
2017-04-30 23:40:29 +00:00
|
|
|
local pop
|
|
|
|
|
2017-05-01 01:01:19 +00:00
|
|
|
import graphics, mouse from love
|
2017-04-30 23:40:29 +00:00
|
|
|
|
|
|
|
path = (...)\sub 1, -7
|
|
|
|
element = require "#{path}/element"
|
|
|
|
|
2017-05-01 01:01:19 +00:00
|
|
|
path = path\sub 1, -11
|
|
|
|
maximizeImage = graphics.newImage "#{path}/images/maximize.png"
|
|
|
|
minimizeImage = graphics.newImage "#{path}/images/minimize.png"
|
|
|
|
closeImage = graphics.newImage "#{path}/images/close.png"
|
|
|
|
-- drag to resize is based on area of padding, which defaults to 5 pixels
|
2016-10-31 05:19:24 +00:00
|
|
|
|
|
|
|
class window extends element
|
2017-04-30 23:40:29 +00:00
|
|
|
load: (pop_lib) ->
|
|
|
|
pop = pop_lib
|
|
|
|
|
2016-08-23 04:22:13 +00:00
|
|
|
--- Constructor expects nothing, or a data table describing it.
|
2017-04-30 23:40:29 +00:00
|
|
|
--- @todo document containMethod values
|
|
|
|
new: (@parent, @data={}, title="Window") =>
|
2016-10-31 05:19:24 +00:00
|
|
|
super @parent, @data
|
|
|
|
|
2016-11-25 03:37:53 +00:00
|
|
|
@data.type = "window"
|
2017-04-30 23:40:29 +00:00
|
|
|
@data.w = 100 unless @data.w > 0
|
|
|
|
@data.h = 80 unless @data.h > 0
|
2017-05-01 01:01:19 +00:00
|
|
|
|
|
|
|
-- how a window is contained within its parent element
|
2017-04-30 23:40:29 +00:00
|
|
|
@data.containMethod = "mouse" unless @data.containMethod
|
|
|
|
|
2017-05-01 01:01:19 +00:00
|
|
|
@data.maximized = false
|
|
|
|
@data.maximizeable = false if @data.maximizeable == nil
|
|
|
|
@data.minimizeable = false if @data.minimizeable == nil
|
|
|
|
@data.closeable = false if @data.closeable == nil
|
|
|
|
unless @data.previous
|
|
|
|
@data.previous = {}
|
|
|
|
|
2017-04-30 23:40:29 +00:00
|
|
|
@header = pop.box @, @data.titleBackground or {25, 180, 230, 255}
|
|
|
|
@title = pop.text @header, {horizontal: "center"}, title, @data.titleColor or {255, 255, 255, 255}
|
2017-05-01 01:01:19 +00:00
|
|
|
@window_area = pop.box @, {padding: 5}, @data.windowBackground or {200, 200, 210, 255}
|
|
|
|
|
|
|
|
-- buttons! :D
|
|
|
|
@data.header_width_reduction = 0
|
|
|
|
buttonSize = @title\getHeight! + 1
|
|
|
|
if @data.closeable
|
|
|
|
@closeButton = pop.box(@, {w: buttonSize, h: buttonSize, horizontalMargin: @data.header_width_reduction}, closeImage)\align "right"
|
|
|
|
@closeButton.clicked = (x, y, button) =>
|
|
|
|
if button == pop.constants.left_mouse
|
|
|
|
@parent\close!
|
|
|
|
@data.header_width_reduction += buttonSize
|
|
|
|
if @data.maximizeable
|
|
|
|
@maximizeButton = pop.box(@, {w: buttonSize, h: buttonSize, horizontalMargin: @data.header_width_reduction}, maximizeImage)\align "right"
|
|
|
|
@maximizeButton.clicked = (x, y, button) =>
|
|
|
|
if button == pop.constants.left_mouse
|
|
|
|
@parent\maximize!
|
|
|
|
@data.header_width_reduction += buttonSize
|
|
|
|
if @data.minimizeable
|
|
|
|
@minimizeButton = pop.box(@, {w: buttonSize, h: buttonSize, horizontalMargin: @data.header_width_reduction}, minimizeImage)\align "right"
|
|
|
|
@minimizeButton.clicked = (x, y, button) =>
|
|
|
|
if button == pop.constants.left_mouse
|
|
|
|
@parent\minimize!
|
|
|
|
@data.header_width_reduction += buttonSize
|
|
|
|
|
|
|
|
height = @title\getHeight! + 1
|
|
|
|
@header\setSize @data.w - @data.header_width_reduction, height
|
2017-04-30 23:40:29 +00:00
|
|
|
@window_area\setSize @data.w, @data.h - height
|
|
|
|
@window_area\move nil, height
|
|
|
|
|
|
|
|
-- window area steals mouse events to prevent propagation to elements under it
|
2017-05-01 01:01:19 +00:00
|
|
|
@window_area.mousepressed = (x, y, button) =>
|
2017-04-30 23:40:29 +00:00
|
|
|
if button == pop.constants.left_mouse
|
|
|
|
grandparent = @parent.parent
|
|
|
|
table.insert grandparent.child, table.remove(grandparent.child, grandparent\indexOf @parent)
|
|
|
|
return nil
|
2017-05-01 01:01:19 +00:00
|
|
|
@window_area.clicked = =>
|
2017-04-30 23:40:29 +00:00
|
|
|
return nil
|
|
|
|
|
2017-05-01 20:45:04 +00:00
|
|
|
--print "window_area " .. tostring @window_area
|
|
|
|
|
2017-04-30 23:40:29 +00:00
|
|
|
selected = false
|
|
|
|
mx = 0
|
|
|
|
my = 0
|
|
|
|
|
|
|
|
@header.mousemoved = (x, y, dx, dy) =>
|
|
|
|
if selected
|
|
|
|
@parent\move dx, dy
|
|
|
|
-- do not leave area of grandparent (based on containMethod)
|
|
|
|
grandparent = @parent.parent
|
|
|
|
switch @parent.data.containMethod
|
|
|
|
when "title" -- the window title can't leave
|
|
|
|
@parent\move(grandparent.data.x - @data.x) if @data.x < grandparent.data.x
|
|
|
|
@parent\move(nil, grandparent.data.y - @data.y) if @data.y < grandparent.data.y
|
|
|
|
@parent\move(grandparent.data.x + grandparent.data.w - (@data.x + @data.w)) if @data.x + @data.w > grandparent.data.x + grandparent.data.w
|
|
|
|
@parent\move(nil, grandparent.data.y + grandparent.data.h - (@data.y + @data.h)) if @data.y + @data.h > grandparent.data.y + grandparent.data.h
|
|
|
|
when "body" -- the entire window can't leave
|
|
|
|
@parent\move(grandparent.data.x - @data.x) if @data.x < grandparent.data.x
|
|
|
|
@parent\move(nil, grandparent.data.y - @data.y) if @data.y < grandparent.data.y
|
|
|
|
@parent\move(grandparent.data.x + grandparent.data.w - (@parent.data.x + @parent.data.w)) if @parent.data.x + @parent.data.w > grandparent.data.x + grandparent.data.w
|
|
|
|
@parent\move(nil, grandparent.data.y + grandparent.data.h - (@parent.data.y + @parent.data.h)) if @parent.data.y + @parent.data.h > grandparent.data.y + grandparent.data.h
|
|
|
|
when "mouse" -- wherever the mouse has clicked can't leave
|
|
|
|
@parent\setPosition(grandparent.data.x + @data.w - mx) if mouse.getX! < grandparent.data.x
|
|
|
|
@parent\setPosition(nil, grandparent.data.y + @parent.data.h - my) if mouse.getY! < grandparent.data.y
|
|
|
|
@parent\setPosition(grandparent.data.x + grandparent.data.w + @data.w - mx) if mouse.getX! > grandparent.data.x + grandparent.data.w
|
|
|
|
@parent\setPosition(nil, grandparent.data.y + grandparent.data.h + @parent.data.h - my) if mouse.getY! > grandparent.data.y + grandparent.data.h
|
|
|
|
return true
|
|
|
|
return false
|
|
|
|
|
|
|
|
@header.mousepressed = (x, y, button) =>
|
|
|
|
if button == pop.constants.left_mouse
|
|
|
|
grandparent = @parent.parent
|
|
|
|
table.insert grandparent.child, table.remove(grandparent.child, grandparent\indexOf @parent)
|
|
|
|
selected = true
|
|
|
|
mx = x
|
|
|
|
my = y
|
|
|
|
return true
|
|
|
|
return false
|
|
|
|
|
|
|
|
@header.mousereleased = (x, y, button) =>
|
|
|
|
if button == pop.constants.left_mouse
|
|
|
|
selected = false
|
|
|
|
return true
|
|
|
|
return false
|
|
|
|
|
|
|
|
@align!
|
|
|
|
|
|
|
|
align: (...) =>
|
|
|
|
unless @data.align return @
|
|
|
|
super ...
|
|
|
|
|
|
|
|
@header\align!
|
|
|
|
@title\align!
|
|
|
|
@window_area\align!
|
2017-05-01 01:01:19 +00:00
|
|
|
if @closeButton
|
|
|
|
@closeButton\align!
|
|
|
|
if @maximizeButton
|
|
|
|
@maximizeButton\align!
|
|
|
|
if @minimizeButton
|
|
|
|
@minimizeButton\align!
|
2017-04-30 23:40:29 +00:00
|
|
|
|
|
|
|
@window_area\move nil, @header\getHeight!
|
|
|
|
|
|
|
|
return @
|
|
|
|
|
|
|
|
setSize: (w, h) =>
|
|
|
|
x = 0
|
|
|
|
y = 0
|
|
|
|
|
|
|
|
if w
|
|
|
|
switch @data.horizontal
|
|
|
|
when "center"
|
|
|
|
x -= (w - @data.w) / 2
|
|
|
|
when "right"
|
|
|
|
x -= w - @data.w
|
|
|
|
|
2017-05-01 01:01:19 +00:00
|
|
|
@header\setWidth w - @data.header_width_reduction
|
2017-04-30 23:40:29 +00:00
|
|
|
@window_area\setWidth w
|
|
|
|
@data.w = w
|
|
|
|
@data.x += x
|
|
|
|
|
|
|
|
@title\align!
|
|
|
|
|
|
|
|
if h
|
|
|
|
switch @data.vertical
|
|
|
|
when "center"
|
|
|
|
y -= (h - @data.h) / 2
|
|
|
|
when "right"
|
|
|
|
y -= h - @data.h
|
|
|
|
|
|
|
|
@window_area\setHeight h - @header\getHeight!
|
|
|
|
@window_area\move nil, @header\getHeight!
|
|
|
|
@data.h = h
|
|
|
|
@data.y += y
|
|
|
|
|
|
|
|
@header\move x, y
|
|
|
|
@window_area\move x, y
|
|
|
|
|
|
|
|
return @
|
2016-10-31 06:40:40 +00:00
|
|
|
|
2017-04-30 23:40:29 +00:00
|
|
|
setWidth: (w) =>
|
|
|
|
return @setSize w
|
2016-08-23 04:22:13 +00:00
|
|
|
|
2017-04-30 23:40:29 +00:00
|
|
|
setHeight: (h) =>
|
|
|
|
return @setSize nil, h
|
2017-05-01 01:01:19 +00:00
|
|
|
|
|
|
|
setPadding: (padding) =>
|
|
|
|
@window_area\setPadding padding
|
|
|
|
return @
|
|
|
|
|
|
|
|
getPadding: =>
|
|
|
|
return @window_area\getPadding!
|
|
|
|
|
2017-05-01 02:24:47 +00:00
|
|
|
childAdded: (element) =>
|
|
|
|
table.insert @window_area.data, table.remove @data.child, @dataIndexOf element.data
|
|
|
|
table.insert @window_area, table.remove @child, @indexOf element
|
|
|
|
element\align!
|
|
|
|
print "worked?"
|
|
|
|
return @
|
|
|
|
|
2017-05-01 01:01:19 +00:00
|
|
|
maximize: =>
|
|
|
|
if @data.maximized
|
|
|
|
@data.x = @data.previous.x
|
|
|
|
@data.y = @data.previous.y
|
|
|
|
@setSize @data.previous.w, @data.previous.h
|
|
|
|
else
|
|
|
|
@data.previous.x = @data.x
|
|
|
|
@data.previous.y = @data.y
|
|
|
|
@data.previous.w = @data.w
|
|
|
|
@data.previous.h = @data.h
|
|
|
|
@data.x = @parent.data.x
|
|
|
|
@data.y = @parent.data.y
|
|
|
|
@setSize @parent.data.w, @parent.data.h
|
|
|
|
table.insert @parent.child, table.remove(@parent.child, @parent\indexOf @)
|
|
|
|
@data.maximized = not @data.maximized
|
|
|
|
@align!
|
|
|
|
return @
|
|
|
|
|
|
|
|
minimize: =>
|
|
|
|
@data.draw = false
|
|
|
|
return @
|
|
|
|
|
|
|
|
close: =>
|
|
|
|
@delete!
|