1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-18 19:21:39 +03:00
vimr/VimR/Workspace/WorkspaceBar.swift

552 lines
16 KiB
Swift
Raw Normal View History

2016-09-18 21:49:42 +03:00
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Cocoa
import PureLayout
2016-09-27 19:02:05 +03:00
protocol WorkspaceBarDelegate: class {
func resizeWillStart(workspaceBar: WorkspaceBar)
func resizeDidEnd(workspaceBar: WorkspaceBar)
}
2016-09-18 21:49:42 +03:00
class WorkspaceBar: NSView, WorkspaceToolDelegate {
2016-09-25 18:50:33 +03:00
static fileprivate let separatorColor = NSColor.controlShadowColor
static fileprivate let separatorThickness = CGFloat(1)
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
fileprivate var tools = [WorkspaceTool]()
fileprivate weak var selectedTool: WorkspaceTool?
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
fileprivate var isMouseDownOngoing = false
fileprivate var dragIncrement = CGFloat(1)
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
fileprivate var layoutConstraints = [NSLayoutConstraint]()
2016-09-18 21:49:42 +03:00
2016-09-25 01:44:10 +03:00
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - API
static let minimumDimension = CGFloat(50)
2016-09-25 01:44:10 +03:00
let location: WorkspaceBarLocation
var isButtonVisible = true {
didSet {
self.relayout()
}
}
var isOpen: Bool {
return self.selectedTool != nil
}
2016-09-25 01:44:10 +03:00
var dimensionConstraint = NSLayoutConstraint()
2016-09-27 19:02:05 +03:00
weak var delegate: WorkspaceBarDelegate?
2016-09-18 21:49:42 +03:00
init(location: WorkspaceBarLocation) {
self.location = location
super.init(frame: CGRect.zero)
super.translatesAutoresizingMaskIntoConstraints = false
self.wantsLayer = true
2016-09-25 18:50:33 +03:00
self.layer!.backgroundColor = NSColor.windowBackgroundColor.cgColor
2016-09-18 21:49:42 +03:00
}
2016-09-25 01:44:10 +03:00
func relayout() {
self.removeConstraints(self.layoutConstraints)
self.removeAllSubviews()
2016-09-18 21:49:42 +03:00
2016-09-25 01:44:10 +03:00
if self.isEmpty() {
2016-09-27 19:02:05 +03:00
self.set(dimension: 0)
2016-09-25 01:44:10 +03:00
return
}
2016-09-18 21:49:42 +03:00
if self.isButtonVisible {
2016-09-25 01:44:10 +03:00
self.layoutButtons()
2016-09-18 21:49:42 +03:00
if self.isOpen {
2016-09-25 01:44:10 +03:00
let curTool = self.selectedTool!
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
self.layout(curTool)
2016-09-18 21:49:42 +03:00
2016-09-25 01:44:10 +03:00
let newDimension = self.barDimension(withToolDimension: curTool.dimension)
2016-09-27 19:02:05 +03:00
self.set(dimension: newDimension)
2016-09-25 01:44:10 +03:00
} else {
2016-09-27 19:02:05 +03:00
self.set(dimension: self.barDimensionWithButtonsWithoutTool())
2016-09-25 01:44:10 +03:00
}
2016-09-18 21:49:42 +03:00
2016-09-25 01:44:10 +03:00
} else {
if self.isOpen {
2016-09-25 01:44:10 +03:00
let curTool = self.selectedTool!
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
self.layoutWithoutButtons(curTool)
2016-09-25 01:44:10 +03:00
let newDimension = self.barDimensionWithoutButtons(withToolDimension: curTool.dimension)
2016-09-27 19:02:05 +03:00
self.set(dimension: newDimension)
2016-09-25 01:44:10 +03:00
} else {
2016-09-27 19:02:05 +03:00
self.set(dimension: 0)
2016-09-25 01:44:10 +03:00
}
2016-09-18 21:49:42 +03:00
}
}
2016-09-25 18:50:33 +03:00
func append(tool: WorkspaceTool) {
2016-09-25 01:44:10 +03:00
tool.delegate = self
tool.location = self.location
tools.append(tool)
if self.isOpen {
2016-09-25 01:44:10 +03:00
self.selectedTool?.isSelected = false
self.selectedTool = tool
2016-09-18 21:49:42 +03:00
}
2016-09-25 01:44:10 +03:00
self.relayout()
2016-09-18 21:49:42 +03:00
}
2016-09-25 01:44:10 +03:00
}
2016-09-18 21:49:42 +03:00
2016-09-25 01:44:10 +03:00
// MARK: - NSView
extension WorkspaceBar {
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
2016-09-25 01:44:10 +03:00
if self.isButtonVisible {
self.drawInnerSeparator(dirtyRect)
}
if self.isOpen {
2016-09-25 01:44:10 +03:00
self.drawOuterSeparator(dirtyRect)
2016-09-18 21:49:42 +03:00
}
}
2016-09-27 19:02:05 +03:00
override func hitTest(_ point: NSPoint) -> NSView? {
if self.resizeRect().contains(point) {
return self
}
return super.hitTest(point)
}
2016-09-25 18:50:33 +03:00
override func mouseDown(with event: NSEvent) {
guard self.isOpen else {
2016-09-18 21:49:42 +03:00
return
}
if self.isMouseDownOngoing {
return
}
2016-09-25 18:50:33 +03:00
let initialMouseLoc = self.convert(event.locationInWindow, from: nil)
let mouseInResizeRect = NSMouseInRect(initialMouseLoc, self.resizeRect(), self.isFlipped)
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
guard mouseInResizeRect && event.type == .leftMouseDown else {
super.mouseDown(with: event)
2016-09-18 21:49:42 +03:00
return
}
self.isMouseDownOngoing = true
2016-09-27 19:02:05 +03:00
self.delegate?.resizeWillStart(workspaceBar: self)
2016-09-25 09:50:46 +03:00
self.dimensionConstraint.priority = NSLayoutPriorityDragThatCannotResizeWindow - 1
2016-09-18 21:49:42 +03:00
var dragged = false
var curEvent = event
let nextEventMask: NSEventMask = [
2016-09-25 18:50:33 +03:00
NSEventMask.leftMouseDragged,
NSEventMask.leftMouseDown,
NSEventMask.leftMouseUp
2016-09-18 21:49:42 +03:00
]
2016-09-25 18:50:33 +03:00
while curEvent.type != .leftMouseUp {
2016-09-27 19:02:05 +03:00
let nextEvent = NSApp.nextEvent(matching: nextEventMask,
until: Date.distantFuture,
inMode: RunLoopMode.eventTrackingRunLoopMode,
dequeue: true)
2016-09-18 21:49:42 +03:00
guard nextEvent != nil else {
break
}
curEvent = nextEvent!
2016-09-25 18:50:33 +03:00
guard curEvent.type == .leftMouseDragged else {
2016-09-18 21:49:42 +03:00
break
}
2016-09-25 18:50:33 +03:00
let curMouseLoc = self.convert(curEvent.locationInWindow, from: nil)
2016-09-18 21:49:42 +03:00
let distance = sq(initialMouseLoc.x - curMouseLoc.x) + sq(initialMouseLoc.y - curMouseLoc.y)
guard dragged || distance >= 1 else {
continue
}
2016-09-25 18:50:33 +03:00
let locInSuperview = self.superview!.convert(curEvent.locationInWindow, from: nil)
2016-09-18 21:49:42 +03:00
let newDimension = self.newDimension(forLocationInSuperview: locInSuperview)
2016-09-27 19:02:05 +03:00
self.set(dimension: newDimension)
2016-09-18 21:49:42 +03:00
dragged = true
}
2016-09-25 09:50:46 +03:00
self.dimensionConstraint.priority = NSLayoutPriorityDragThatCannotResizeWindow
2016-09-18 21:49:42 +03:00
self.isMouseDownOngoing = false
2016-09-27 19:02:05 +03:00
self.delegate?.resizeDidEnd(workspaceBar: self)
2016-09-18 21:49:42 +03:00
}
override func resetCursorRects() {
guard self.isOpen else {
2016-09-18 21:49:42 +03:00
return
}
switch self.location {
case .top, .bottom:
2016-09-25 18:50:33 +03:00
self.addCursorRect(self.resizeRect(), cursor: NSCursor.resizeUpDown())
2016-09-18 21:49:42 +03:00
case .right, .left:
2016-09-25 18:50:33 +03:00
self.addCursorRect(self.resizeRect(), cursor: NSCursor.resizeLeftRight())
2016-09-18 21:49:42 +03:00
}
}
2016-09-25 18:50:33 +03:00
fileprivate func drawInnerSeparator(_ dirtyRect: NSRect) {
2016-09-25 01:44:10 +03:00
WorkspaceBar.separatorColor.set()
let innerLineRect = self.innerSeparatorRect()
if dirtyRect.intersects(innerLineRect) {
NSRectFill(innerLineRect)
}
}
2016-09-25 18:50:33 +03:00
fileprivate func drawOuterSeparator(_ dirtyRect: NSRect) {
2016-09-25 01:44:10 +03:00
WorkspaceBar.separatorColor.set()
let outerLineRect = self.outerSeparatorRect()
if dirtyRect.intersects(outerLineRect) {
NSRectFill(outerLineRect)
}
}
2016-09-25 18:50:33 +03:00
fileprivate func buttonSize() -> CGSize {
2016-09-25 01:44:10 +03:00
if self.isEmpty() {
return CGSize.zero
}
return self.tools.first!.button.intrinsicContentSize
}
2016-09-25 18:50:33 +03:00
fileprivate func innerSeparatorRect() -> CGRect {
2016-09-25 01:44:10 +03:00
let bounds = self.bounds
let thickness = WorkspaceBar.separatorThickness
let bar = self.buttonSize()
switch self.location {
case .top:
return CGRect(x: 0, y: bounds.height - bar.height - thickness, width: bounds.width, height: thickness)
case .right:
return CGRect(x: bounds.width - bar.width - thickness, y: 0, width: thickness, height: bounds.height)
case .bottom:
return CGRect(x: 0, y: bar.height, width: bounds.width, height: thickness)
case .left:
return CGRect(x: bar.width, y: 0, width: thickness, height: bounds.height)
}
}
2016-09-25 18:50:33 +03:00
fileprivate func newDimension(forLocationInSuperview locInSuperview: CGPoint) -> CGFloat {
2016-09-18 21:49:42 +03:00
let dimension = self.dimension(forLocationInSuperview: locInSuperview)
return self.dragIncrement * floor(dimension / self.dragIncrement)
}
2016-09-25 18:50:33 +03:00
fileprivate func dimension(forLocationInSuperview locInSuperview: CGPoint) -> CGFloat {
2016-09-18 21:49:42 +03:00
let superviewBounds = self.superview!.bounds
switch self.location {
case .top:
return superviewBounds.height - locInSuperview.y
case .right:
return superviewBounds.width - locInSuperview.x
case .bottom:
return locInSuperview.y
case .left:
return locInSuperview.x
}
}
2016-09-25 18:50:33 +03:00
fileprivate func sq(_ number: CGFloat) -> CGFloat {
2016-09-18 21:49:42 +03:00
return number * number
}
2016-09-25 18:50:33 +03:00
fileprivate func outerSeparatorRect() -> CGRect {
2016-09-18 21:49:42 +03:00
let thickness = WorkspaceBar.separatorThickness
switch self.location {
case .top:
return CGRect(x: 0, y: 0, width: self.bounds.width, height: thickness)
case .right:
return CGRect(x: 0, y: 0, width: thickness, height: self.bounds.height)
case .bottom:
return CGRect(x: 0, y: self.bounds.height - thickness, width: self.bounds.width, height: thickness)
case .left:
return CGRect(x: self.bounds.width - thickness, y: 0, width: thickness, height: self.bounds.height)
}
}
2016-09-25 18:50:33 +03:00
fileprivate func resizeRect() -> CGRect {
2016-09-18 21:49:42 +03:00
let separatorRect = self.outerSeparatorRect()
let clickDimension = CGFloat(4)
switch self.location {
case .top:
return separatorRect.offsetBy(dx: 0, dy: clickDimension).union(separatorRect)
case .right:
return separatorRect.offsetBy(dx: clickDimension, dy: 0).union(separatorRect)
case .bottom:
return separatorRect.offsetBy(dx: 0, dy: -clickDimension).union(separatorRect)
case .left:
return separatorRect.offsetBy(dx: -clickDimension, dy: 0).union(separatorRect)
}
}
2016-09-27 19:02:05 +03:00
fileprivate func set(dimension: CGFloat) {
let saneDimension = self.saneDimension(from: dimension)
self.dimensionConstraint.constant = saneDimension
2016-09-18 21:49:42 +03:00
let toolDimension = self.toolDimension(fromBarDimension: saneDimension)
if self.isOpen {
2016-09-18 21:49:42 +03:00
self.selectedTool?.dimension = toolDimension
}
2016-09-27 19:02:05 +03:00
// In 10.12 we need the following, otherwise resizing the tools does not work correctly.
self.layoutSubtreeIfNeeded()
self.window?.invalidateCursorRects(for: self)
self.needsDisplay = true
2016-09-18 21:49:42 +03:00
}
fileprivate func saneDimension(from dimension: CGFloat) -> CGFloat {
if dimension == 0 {
return 0
}
if self.isOpen {
return max(dimension, self.selectedTool!.minimumDimension, WorkspaceBar.minimumDimension)
}
return max(dimension, self.barDimensionWithButtonsWithoutTool())
}
2016-09-25 01:44:10 +03:00
}
// MARK: - Layout
extension WorkspaceBar {
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
fileprivate func isEmpty() -> Bool {
2016-09-18 21:49:42 +03:00
return self.tools.isEmpty
}
2016-09-25 18:50:33 +03:00
fileprivate func hasTools() -> Bool {
2016-09-18 21:49:42 +03:00
return !self.isEmpty()
}
2016-09-25 18:50:33 +03:00
fileprivate func layoutWithoutButtons(_ tool: WorkspaceTool) {
2016-09-18 21:49:42 +03:00
let view = tool.view
let thickness = WorkspaceBar.separatorThickness
self.addSubview(view)
switch self.location {
case .top:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
view.autoPinEdge(toSuperviewEdge: .top),
view.autoPinEdge(toSuperviewEdge: .right),
view.autoPinEdge(toSuperviewEdge: .bottom, withInset: thickness),
view.autoPinEdge(toSuperviewEdge: .left),
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
view.autoSetDimension(.height, toSize: tool.minimumDimension, relation: .greaterThanOrEqual)
2016-09-18 21:49:42 +03:00
])
case .right:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
view.autoPinEdge(toSuperviewEdge: .top),
view.autoPinEdge(toSuperviewEdge: .right),
view.autoPinEdge(toSuperviewEdge: .bottom),
view.autoPinEdge(toSuperviewEdge: .left, withInset: thickness),
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
view.autoSetDimension(.width, toSize: tool.minimumDimension, relation: .greaterThanOrEqual)
2016-09-18 21:49:42 +03:00
])
case .bottom:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
view.autoPinEdge(toSuperviewEdge: .top, withInset: thickness),
view.autoPinEdge(toSuperviewEdge: .right),
view.autoPinEdge(toSuperviewEdge: .bottom),
view.autoPinEdge(toSuperviewEdge: .left),
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
view.autoSetDimension(.height, toSize: tool.minimumDimension, relation: .greaterThanOrEqual)
2016-09-18 21:49:42 +03:00
])
case .left:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
view.autoPinEdge(toSuperviewEdge: .top),
view.autoPinEdge(toSuperviewEdge: .right, withInset: thickness),
view.autoPinEdge(toSuperviewEdge: .bottom),
view.autoPinEdge(toSuperviewEdge: .left),
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
view.autoSetDimension(.width, toSize: tool.minimumDimension, relation: .greaterThanOrEqual)
2016-09-18 21:49:42 +03:00
])
}
}
2016-09-25 18:50:33 +03:00
fileprivate func layout(_ tool: WorkspaceTool) {
2016-09-18 21:49:42 +03:00
let view = tool.view
let button = tool.button
let thickness = WorkspaceBar.separatorThickness
self.addSubview(view)
switch self.location {
case .top:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
view.autoPinEdge(.top, to: .bottom, of: button, withOffset: thickness),
view.autoPinEdge(toSuperviewEdge: .right),
view.autoPinEdge(toSuperviewEdge: .bottom, withInset: thickness),
view.autoPinEdge(toSuperviewEdge: .left),
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
view.autoSetDimension(.height, toSize: tool.minimumDimension, relation: .greaterThanOrEqual)
2016-09-18 21:49:42 +03:00
])
case .right:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
view.autoPinEdge(toSuperviewEdge: .top),
view.autoPinEdge(.right, to: .left, of: button, withOffset: -thickness), // Offset is count l -> r,
view.autoPinEdge(toSuperviewEdge: .bottom),
view.autoPinEdge(toSuperviewEdge: .left, withInset: thickness),
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
view.autoSetDimension(.width, toSize: tool.minimumDimension, relation: .greaterThanOrEqual)
2016-09-18 21:49:42 +03:00
])
case .bottom:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
view.autoPinEdge(toSuperviewEdge: .top, withInset: thickness),
view.autoPinEdge(toSuperviewEdge: .right),
view.autoPinEdge(.bottom, to: .top, of: button, withOffset: -thickness), // Offset is count t -> b,
view.autoPinEdge(toSuperviewEdge: .left),
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
view.autoSetDimension(.height, toSize: tool.minimumDimension, relation: .greaterThanOrEqual)
2016-09-18 21:49:42 +03:00
])
case .left:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
view.autoPinEdge(toSuperviewEdge: .top),
view.autoPinEdge(toSuperviewEdge: .right, withInset: thickness),
view.autoPinEdge(toSuperviewEdge: .bottom),
view.autoPinEdge(.left, to: .right, of: button, withOffset: thickness),
2016-09-18 21:49:42 +03:00
2016-09-25 18:50:33 +03:00
view.autoSetDimension(.width, toSize: tool.minimumDimension, relation: .greaterThanOrEqual)
2016-09-18 21:49:42 +03:00
])
}
}
2016-09-25 18:50:33 +03:00
fileprivate func layoutButtons() {
2016-09-18 21:49:42 +03:00
guard let firstTool = self.tools.first else {
return
}
self.tools
.map { $0.button }
.forEach(self.addSubview)
let firstButton = firstTool.button
switch self.location {
case .top:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
firstButton.autoPinEdge(toSuperviewEdge: .top),
firstButton.autoPinEdge(toSuperviewEdge: .left),
2016-09-18 21:49:42 +03:00
])
case .right:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
firstButton.autoPinEdge(toSuperviewEdge: .top),
firstButton.autoPinEdge(toSuperviewEdge: .right),
2016-09-18 21:49:42 +03:00
])
case .bottom:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
firstButton.autoPinEdge(toSuperviewEdge: .left),
firstButton.autoPinEdge(toSuperviewEdge: .bottom),
2016-09-18 21:49:42 +03:00
])
case .left:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
firstButton.autoPinEdge(toSuperviewEdge: .top),
firstButton.autoPinEdge(toSuperviewEdge: .left),
2016-09-18 21:49:42 +03:00
])
}
var lastButton = firstButton
for button in self.tools[1..<self.tools.count].map({ $0.button }) {
switch self.location {
case .top:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
button.autoPinEdge(toSuperviewEdge: .top),
button.autoPinEdge(.left, to: .right, of: lastButton),
2016-09-18 21:49:42 +03:00
])
case .right:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
button.autoPinEdge(.top, to: .bottom, of: lastButton),
button.autoPinEdge(toSuperviewEdge: .right),
2016-09-18 21:49:42 +03:00
])
case .bottom:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
button.autoPinEdge(.left, to: .right, of: lastButton),
button.autoPinEdge(toSuperviewEdge: .bottom),
2016-09-18 21:49:42 +03:00
])
case .left:
2016-09-25 18:50:33 +03:00
self.layoutConstraints.append(contentsOf: [
button.autoPinEdge(.top, to: .bottom, of: lastButton),
button.autoPinEdge(toSuperviewEdge: .left),
2016-09-18 21:49:42 +03:00
])
}
lastButton = button
}
}
2016-09-25 18:50:33 +03:00
fileprivate func barDimensionWithButtonsWithoutTool() -> CGFloat {
2016-09-18 21:49:42 +03:00
switch self.location {
case .top, .bottom:
return self.buttonSize().height + WorkspaceBar.separatorThickness
case .right, .left:
return self.buttonSize().width + WorkspaceBar.separatorThickness
}
}
2016-09-25 18:50:33 +03:00
fileprivate func barDimensionWithoutButtons(withToolDimension toolDimension: CGFloat) -> CGFloat {
2016-09-18 21:49:42 +03:00
return toolDimension + WorkspaceBar.separatorThickness
}
2016-09-25 18:50:33 +03:00
fileprivate func barDimension(withToolDimension toolDimension: CGFloat) -> CGFloat {
2016-09-18 21:49:42 +03:00
return self.barDimensionWithButtonsWithoutTool() + toolDimension + WorkspaceBar.separatorThickness
}
2016-09-25 18:50:33 +03:00
fileprivate func toolDimension(fromBarDimension barDimension: CGFloat) -> CGFloat {
2016-09-18 21:49:42 +03:00
if self.isButtonVisible {
return barDimension - WorkspaceBar.separatorThickness - barDimensionWithButtonsWithoutTool()
}
return barDimension - WorkspaceBar.separatorThickness
}
}
// MARK: - WorkspaceToolDelegate
extension WorkspaceBar {
2016-09-25 18:50:33 +03:00
func toggle(_ tool: WorkspaceTool) {
2016-09-27 19:02:05 +03:00
self.delegate?.resizeWillStart(workspaceBar: self)
if self.isOpen {
2016-09-18 21:49:42 +03:00
let curTool = self.selectedTool!
if curTool === tool {
// In this case, curTool.isSelected is already set to false in WorkspaceTool.toggle()
self.selectedTool = nil
} else {
curTool.isSelected = false
self.selectedTool = tool
}
} else {
self.selectedTool = tool
}
self.relayout()
2016-09-27 19:02:05 +03:00
self.delegate?.resizeDidEnd(workspaceBar: self)
2016-09-18 21:49:42 +03:00
}
}