UNPKG

coffeescript-ui

Version:
517 lines (401 loc) 10.9 kB
### * coffeescript-ui - Coffeescript User Interface System (CUI) * Copyright (c) 2013 - 2016 Programmfabrik GmbH * MIT Licence * https://github.com/programmfabrik/coffeescript-ui, http://www.coffeescript-ui.org ### # this class initializes a flex handle class CUI.FlexHandle extends CUI.Element constructor: (opts) -> super(opts) @__pane = null children = @_element.parentNode.children for c, idx in children if CUI.dom.is(c, @_pane) @__pane = c @__pane_idx = idx if CUI.dom.is(c, @_element) @__element_idx = idx @__adjacent_pane = null if @__element_idx > @__pane_idx if @__element_idx < children.length-1 @__adjacent_pane = children[@__element_idx+1] else if @__element_idx > 0 @__adjacent_pane = children[@__element_idx-1] @__closed = @_closed @__hidden = @_hidden @__stretched = null @__size = null CUI.util.assert(@__pane, "new #{@__cls}", "pane \"#{@_pane}\" not found in parent element of cui-flex-handle element.", opts: @opts, children: children) CUI.dom.data(@__pane, "flexHandle", @) CUI.dom.setAttribute(@__pane, "flex-handled-pane", @_name) readOpts: -> super() if @_direction in ["horizontal", "row"] @__direction = "row" else if @_direction in ["vertical", "column"] @__direction = "column" CUI.util.assert(@__direction in ["row", "column"], "new #{@__cls}", "opts.direction needs to be set", opts: @opts, element: @_element) if @_label @addLabel(@_label) return initOpts: -> super() @addOpts element: mandatory: true check: (v) -> CUI.util.isElement(v) pane: mandatory: true check: String name: mandatory: true check: String closed: check: Boolean closable: mandatory: true default: false check: Boolean label: check: (v) -> v instanceof CUI.Label or CUI.util.isPlainObject(v) hidden: check: Boolean direction: check: ["horizontal", "vertical", "row", "column"] manage_state: default: true check: Boolean state_name: check: String class: check: String init: -> if @isDestroyed() return CUI.dom.addClass(@_element, "cui-flex-handle cui-flex-handle-#{@__direction} cui-flex-handle-#{@_name}") if @__closed @close() if @__hidden @hide() if @_class CUI.dom.addClass(@_element, @_class) if @__direction == "row" axis = "x" @__css_value = "Width" else axis = "y" @__css_value = "Height" CUI.Events.listen type: "dblclick" node: @_element call: (ev) => if @__size == null # CUI.util.isEmpty(@__pane[0].style[@__css_value]) if @isClosed() @open() else if @_closable @close() else @resetSize() @storeState() return CUI.Events.listen type: ["click"] node: @_element call: (ev) => if not @__label return if @isClosed() @open() @storeState() return # console.debug @_name, cursor, axis, css_value, @__pane_idx, @__element_idx drag_start_size = null new CUI.Draggable element: @_element axis: axis support_touch: true create: => if @isClosed() return false # helper_remove_always: true dragstart: (ev, gd) => if @__pane_idx < @__element_idx flip = 1 else flip = -1 get_data = (pane) => dim = CUI.dom.getDimensions(pane) min = dim["min"+@__css_value] if min < 10 min = 10 min: min max: dim["max"+@__css_value] value: dim["contentBox"+@__css_value] data = get_data(@__pane) if @__adjacent_pane adj_data = get_data(@__adjacent_pane) max_diff = adj_data.value - adj_data.min # this is the maximum change for the adj value data.max = Math.max(0, data.value+max_diff) drag_start_size = @__pane.style[@__css_value.toLowerCase()] gd.__pane_data = flip: flip axis: axis min: data.min max: data.max value: data.value gd.isFlexHandleDrag = true gd get_cursor: (gd) -> if gd.__pane_data.axis == "x" return "ew-resize" else return "ns-resize" dragend: (ev, gd) => dragging(gd) @__size = CUI.dom.getDimension(@__pane, "contentBox"+@__css_value) @storeState() dragstop: => @__pane.style[@__css_value.toLowerCase()] = drag_start_size drag_start_size = null @__resize() dragging: (ev, gd) => if !CUI.__ng__ || CUI.browser.ie return dragging(gd) dragging = (gd) => new_value = gd.__pane_data.value + gd.dragDiff[gd.__pane_data.axis] * gd.__pane_data.flip if gd.__pane_data.min new_value = Math.max(gd.__pane_data.min, new_value) if gd.__pane_data.max new_value = Math.min(gd.__pane_data.max, new_value) @__setSize(new_value) if @_manage_state if not @_state_name console.error "new CUI.FlexHandle()", "opts.state_name missing, state will not be stored.", @opts @__state_name = @_state_name @__setState() @ __setSize: (size) -> if CUI.util.isNull(size) CUI.dom.setStyleOne(@__pane, @__css_value.toLowerCase(), "") if @__isAlive() if CUI.dom.getDimension(@__pane, "contentBox"+@__css_value) == 0 console.error("FlexHandle.__setSize: Pane size is 0 if unset, this needs to be fixed in CSS.", @__pane) CUI.dom.setDimension(@__pane, "contentBox"+@__css_value, 100) @__pane.classList.remove("cui-is-manually-sized") @_element.classList.remove("cui-is-manually-sized") @__size = null else @__pane.classList.add("cui-is-manually-sized") @_element.classList.add("cui-is-manually-sized") CUI.dom.setDimension(@__pane, "contentBox"+@__css_value, size) @__size = size @__resize() resetSize: -> @__setSize(null) @ __getSize: -> @__size __isAlive: -> if @isDestroyed() or not CUI.dom.isInDOM(@_element) false else true __resize: -> # console.debug "FlexHandle.__resize", @__uniqueId, @isDestroyed(), @__isInDOM, @__isAlive() if not @__isAlive() return # console.info "FlexHandle[#{@getName()}].resize." CUI.Events.trigger type: "viewport-resize" info: FlexHandle: true __getState: -> value = CUI.getLocalStorage(@__state_name) if not CUI.util.isNull(value) state = JSON.parse(value) else state = {} state __setState: -> if not @__state_name return state = @__getState() if not CUI.util.isUndef(state.closed) and @_closable if state.closed @close() else @open() if not CUI.util.isUndef(state.size) @__setSize(state.size) # console.debug "setState", state @ storeState: -> if not @__state_name return state = closed: @isClosed() size: @__getSize() value = JSON.stringify(state) CUI.setLocalStorage(@__state_name, value) console.info("FlexHandle.storeState: ", @__state_name, value) @ isStretched: -> @__stretched stretch: (direction, do_stretch = true) -> if do_stretch if @isStretched() == direction return else @unstretch() pane = @getPane() switch direction when "west", "north" els = CUI.dom.findPreviousSiblings(pane) when "east", "south" els = CUI.dom.findNextSiblings(pane) switch direction when "west", "east" set = "width" when "north", "south" set = "height" if do_stretch # first we set all the value to explicit "px" # so that the transition works for el in els el.classList.add("cui-flex-handle-hide-for-stretch") el.classList.add("cui-flex-handle-hide-for-stretch-#{direction}") CUI.dom[set](@__pane, "") pane.classList.add("cui-flex-handle-stretched") pane.classList.add("cui-flex-handle-stretched-#{direction}") CUI.Events.trigger node: pane type: "flex-stretch-start" @__stretched = direction else for el in els el.classList.remove("cui-flex-handle-hide-for-stretch") el.classList.remove("cui-flex-handle-hide-for-stretch-#{direction}") @__stretched = null if @__size @__pane[set](@__size) pane.classList.remove("cui-flex-handle-stretched") pane.classList.remove("cui-flex-handle-stretched-#{direction}") CUI.Events.trigger node: pane type: "flex-stretch-end" @__resize() @ unstretch: -> if not @isStretched() return @stretch(@__stretched, false) getLabel: -> if not @__isAlive() return null @__label addLabel: (opts={}) -> if opts instanceof CUI.Label @__label = opts else if @__direction == "row" opts.rotate_90 = true @__label = new CUI.defaults.class.Label(opts) CUI.dom.append(@_element, @__label.DOM) CUI.dom.addClass(@_element, "cui-flex-handle-has-label") getName: -> @_name getHandle: -> @_element getPane: -> @__pane isShown: -> not @isHidden() isHidden: -> @_element.classList.contains("cui-flex-handle-hidden") isClosed: -> @_element.classList.contains("cui-flex-handle-closed") isOpen: -> not @isClosed() close: -> if @isClosed() return @ CUI.Events.trigger node: @getPane() type: "flex-close" @_element.classList.add("cui-flex-handle-closed") CUI.dom.setStyleOne(@__pane, "display", "none") @__resize() @ open: -> if @isOpen() return @ CUI.Events.trigger node: @getPane() type: "flex-open" @_element.classList.remove("cui-flex-handle-closed") CUI.dom.setStyleOne(@__pane, "display", "") delete(@__closed) @__resize() @ hide: -> if @isHidden() return @ @_element.classList.add("cui-flex-handle-hidden") @__resize() @ show: -> if @isShown() return @ @_element.classList.remove("cui-flex-handle-hidden") delete(@__hidden) @__resize() @ destroy: -> CUI.dom.removeData(@__pane, "flexHandle") CUI.dom.removeAttribute(@__pane, "flex-handled-pane") CUI.dom.remove(@_element) super() @getStretchButton: (_opts={}) -> opts = CUI.Element.readOpts _opts, "FlexHandle.getPushButton", direction: check: ["west","east","north","south"] text: check: String flexHandle: check: CUI.FlexHandle button: default: {} activedir = west: "east" east: "west" north: "south" south: "north" btn_opts = opts.button for k, v of { icon_active: activedir[opts.direction] icon_inactive: opts.direction class: "cui-pane-stretch-button" text: opts.text switch: true onClick: (ev, btn) => if opts.flexHandle fh = opts.flexHandle else fh_els = CUI.dom.closest(btn.DOM, "[flex-handled-pane]") CUI.util.assert(fh_els, "FlexHandle.getStretchButton", "FlexHandle not or more than one found, name: #{opts.name}.", opts: opts, flexHandles: fh_els) fh = CUI.dom.data(fh_els, "flexHandle") if fh.isStretched() fh.unstretch() else fh.stretch(opts.direction) } btn_opts[k] = v new CUI.defaults.class.Button(btn_opts) CUI.Events.registerEvent type: ["flex-stretch-start", "flex-stretch-end", "flex-close", "flex-open"] sink: true