Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refractor methods, items, etc #295

Merged
merged 12 commits into from
Apr 29, 2020
202 changes: 135 additions & 67 deletions lib/items/tool-bar-button-view.js
Original file line number Diff line number Diff line change
@@ -1,89 +1,155 @@
const {CompositeDisposable} = require('atom');
const { ToolBarItem } = require('./tool-bar-item');

/**
* A button class with many options
*
* @property {HTMLElement} element
* @property {number} priority
* @property {string} group
*
* @property {ButtonOptions} options
* @property {boolean} enabled
* @property {CompositeDisposable} subscriptions
*/
class ToolBarButtonView extends ToolBarItem {
/**
*
* @param {ButtonOptions} options
* @param {string} group
*/
constructor (options, group) {
// first calling the super (ToolBarItem) constructor
super({
element: document.createElement('button'),
priority: options.priority
}, group);

this.subscriptions = new CompositeDisposable();
this.options = options;
this.enabled = true;

if (options.tooltip) {
const callback = this.options.callback;
// default classes
this.classNames = ['btn', 'btn-default', 'tool-bar-btn'];

let tooltip = {};
if (typeof options.tooltip === 'string') {
tooltip = {
title: options.tooltip
};
} else {
tooltip = options.tooltip;
}
if (this.priority < 0) {
this.putAtEnd();
}

if (!tooltip.hasOwnProperty('placement')) {
tooltip.placement = getTooltipPlacement;
}
if (options.icon) {
this.addIcon();
}

if (!tooltip.hasOwnProperty('keyBindingCommand')) {
tooltip.keyBindingCommand = typeof callback === 'string' ? callback : null;
}
if (options.text) {
this.addText();
}

if (options.tooltip) {
this.subscriptions = new CompositeDisposable();
this.subscriptions.add(
atom.tooltips.add(this.element, tooltip)
this.addTooltip(this.options.tooltip, this.options.callback)
);
}

const classNames = ['btn', 'btn-default', 'tool-bar-btn'];
if (this.priority < 0) {
classNames.push('tool-bar-item-align-end');
if (options.color) {
this.addColor();
}
if (options.icon) {
if (options.iconset) {
if (options.iconset.startsWith('fa')) {
classNames.push(options.iconset, `fa-${options.icon}`);
} else {
classNames.push(options.iconset, `${options.iconset}-${options.icon}`);
}
} else {
classNames.push(`icon-${options.icon}`);
}
if (options.background) {
this.addBackgroundColor();
}

if (options.text) {
if (options.html) {
this.element.innerHTML = options.text;
this.addClasses();
this.addOnMouseDown();
this.addOnClick();
}

destroy () {
if (this.subscriptions) {
this.subscriptions.dispose();
this.subscriptions = null;
}
this.element.removeEventListener('mousedown', this._onMouseDown);
this.element.removeEventListener('click', this._onClick);
super.destroy(); // call super.destroy() in the end
}

/** Put the button at the end of the toolbar using 'tool-bar-item-align-end' class. */
putAtEnd () {
this.classNames.push('tool-bar-item-align-end');
}

/** Add an icon for the button using built-in icons. */
addIcon () {
if (this.options.iconset) {
if (this.options.iconset.startsWith('fa')) {
this.classNames.push(this.options.iconset, `fa-${this.options.icon}`);
} else {
this.element.textContent = options.text;
this.classNames.push(this.options.iconset, `${this.options.iconset}-${this.options.icon}`);
}
} else {
this.classNames.push(`icon-${this.options.icon}`);
}
}

if (options.color) {
this.element.style.color = options.color;
/** Adds a text/html to the button */
addText () {
if (this.options.html) {
this.element.innerHTML = this.options.text;
} else {
this.element.textContent = this.options.text;
}
if (options.background) {
this.element.style.background = options.background;
}

/**
* adds a Tooltip for your item.
* @param {ButtonOptions.tooltip} tooltipOptions
* @param {ButtonOptions.callback | null} callback
* @returns {Disposable} a disposable tooltip
*/
addTooltip (tooltipOptions, callback = null) {
let tooltip;
if (typeof tooltipOptions === 'string') {
tooltip = {
title: tooltipOptions
};
} else {
tooltip = tooltipOptions;
}

if (options.class) {
if (Array.isArray(options.class)) {
this.element.classList.add(...options.class);
} else {
this.element.classList.add(options.class);
}
if (!tooltip.hasOwnProperty('placement')) {
tooltip.placement = getTooltipPlacement();
}

if (!tooltip.hasOwnProperty('keyBindingCommand') &&
typeof callback === 'string'
) {
tooltip.keyBindingCommand = callback;
}

this.element.classList.add(...classNames);
return atom.tooltips.add(this.element, tooltip);
}

this._onMouseDown = this._onMouseDown.bind(this);
this._onClick = this._onClick.bind(this);
/** Add color to the button */
addColor () {
this.element.style.color = this.options.color;
}

this.element.addEventListener('mousedown', this._onMouseDown);
this.element.addEventListener('click', this._onClick);
/** Add background color to the button */
addBackgroundColor () {
this.element.style.background = this.options.background;
}

/** Add all the classes (custom and others) to the button */
addClasses () {
// add custom classes to the button
if (this.options.class) {
if (Array.isArray(this.options.class)) {
this.classNames.push(...this.options.class);
} else {
this.element.classList.add(this.options.class);
}
}
// add other classes
this.element.classList.add(...this.classNames);
}

setEnabled (enabled) {
Expand All @@ -107,21 +173,21 @@ class ToolBarButtonView extends ToolBarItem {
return this.element.classList.contains('selected');
}

destroy () {
if (this.subscriptions) {
this.subscriptions.dispose();
this.subscriptions = null;
}
this.element.removeEventListener('mousedown', this._onMouseDown);
this.element.removeEventListener('click', this._onClick);
super.destroy(); // call super.destroy() in the end
addOnMouseDown () {
this._onMouseDown = this._onMouseDown.bind(this);
this.element.addEventListener('mousedown', this._onMouseDown);
}

_onMouseDown (e) {
// Avoid taking focus so we can dispatch Atom commands with the correct target.
e.preventDefault();
}

addOnClick () {
this._onClick = this._onClick.bind(this);
this.element.addEventListener('click', this._onClick);
}

_onClick (e) {
if (this.element && !this.element.classList.contains('disabled')) {
this.executeCallback(e);
Expand Down Expand Up @@ -156,15 +222,6 @@ class ToolBarButtonView extends ToolBarItem {
}
}
}
};

function getTooltipPlacement () {
const toolbarPosition = atom.config.get('tool-bar.position');
return toolbarPosition === 'Top' ? 'bottom'
: toolbarPosition === 'Right' ? 'left'
: toolbarPosition === 'Bottom' ? 'top'
: toolbarPosition === 'Left' ? 'right'
: null;
}

function getCallbackModifier (callback, {altKey, ctrlKey, shiftKey}) {
Expand All @@ -190,4 +247,15 @@ function getCallbackModifier (callback, {altKey, ctrlKey, shiftKey}) {
return callback[modifier] || callback[''];
}

/** get the tooltip placement based on the toolbar position */
function getTooltipPlacement () {
const toolbarPosition = atom.config.get('tool-bar.position');

return toolbarPosition === 'Top' ? 'bottom'
: toolbarPosition === 'Right' ? 'left'
: toolbarPosition === 'Bottom' ? 'top'
: toolbarPosition === 'Left' ? 'right'
: null;
}

module.exports.ToolBarButtonView = ToolBarButtonView;
7 changes: 7 additions & 0 deletions lib/items/tool-bar-item.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
/**
* A minimal class used to manage custom HTML elements in Toolbar.
* This is supposed to be Super for other classes.
* @property {HTMLElement} element
* @property {number} priority
* @property {string} group
*/
class ToolBarItem {
/**
* @param {ItemOptions} options
* @param {string} group
*/
constructor (options, group) {
this.element = options.element;
this.priority = options.priority;
Expand Down
37 changes: 35 additions & 2 deletions lib/tool-bar-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,61 @@ const { ToolBarItem } = require('./items/tool-bar-item');
const { ToolBarButtonView } = require('./items/tool-bar-button-view');
const { ToolBarSpacerView } = require('./items/tool-bar-spacer-view');

module.exports = class ToolBarManager {
/**
*
* @property {string} group
* @property {ToolBarView} toolBarView
* @property {TouchBarManager} touchBarManager
*/
class ToolBarManager {
/**
*
* @param {string} group
* @param {ToolBarView} toolBarView
* @param {TouchBarManager} touchBarManager
*/
constructor (group, toolBarView, touchBarManager) {
this.group = group;
this.toolBarView = toolBarView;
this.touchBarManager = touchBarManager;
}

/** Adds a custom HTML Element to Toolbar. options: {element, priority} */
/**
* Adds a custom HTML Element to Toolbar. options: {element, priority}
* @param {ItemOptions} options
*/
addItem (options) {
const item = new ToolBarItem(options, this.group);
this.toolBarView.addItem(item);
// this.touchBarManager.addItem(item); // TODO
return item;
}

/**
* Adds a button. The input to this function is a `ButtonOptions` object
* @param {ButtonOptions} options
*/
addButton (options) {
const button = new ToolBarButtonView(options, this.group);
this.toolBarView.addItem(button);
this.touchBarManager.addButton(button);
return button;
}

/**
* Adds a spacer. Optionally, you can pass a `SpacerOptions` object
* @param options
* @return {ToolBarSpacerView}
*/
addSpacer (options) {
const spacer = new ToolBarSpacerView(options, this.group);
this.toolBarView.addItem(spacer);
return spacer;
}

/**
* Use the method removeItems to remove the buttons added by your package. This is particular useful in your package deactivate method, but can be used at any time.
*/
removeItems () {
if (this.toolBarView.items) {
this.toolBarView.items
Expand All @@ -39,7 +66,13 @@ module.exports = class ToolBarManager {
}
}

/**
* The onDidDestroy method takes a function that will be called when the tool-bar package is destroyed. This is useful if your package needs to do cleanup when the tool-bar is deactivated but your package continues running.
* @param {() => void} callback
*/
onDidDestroy (callback) {
this.toolBarView.emitter.on('did-destroy', callback);
}
};

module.exports.ToolBarManager = ToolBarManager;
2 changes: 1 addition & 1 deletion lib/tool-bar.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const ToolBarManager = require('./tool-bar-manager');
const { ToolBarManager } = require('./tool-bar-manager');
const ToolBarView = require('./tool-bar-view');
const TouchBarManager = require('./touch-bar-manager');

Expand Down