From 76a8ef1bf960a8b5ccdee3dac95fe20642706d84 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Mon, 19 Mar 2018 03:16:44 +0900 Subject: [PATCH 01/28] Available to set any font (WIP) --- app/editor/boot.js | 2 +- app/editor/ui/fontselect.js | 28 ++-- app/editor/ui/propertypane.js | 233 +++++++++++++++++----------------- app/editor/ui/toolbar.js | 52 ++++---- 4 files changed, 159 insertions(+), 156 deletions(-) diff --git a/app/editor/boot.js b/app/editor/boot.js index 690721fe..f20ed886 100644 --- a/app/editor/boot.js +++ b/app/editor/boot.js @@ -909,7 +909,7 @@ thin.init_ = function() { selectbox.setWidth(170); }); - toolFamily.addEventListener(componentEventType.ACTION, function(e) { + toolFamily.addEventListener(componentEventType.CHANGE, function(e) { var workspace = thin.core.getActiveWorkspace(); if (workspace) { var selectedFamily = toolFamily.getValue(); diff --git a/app/editor/ui/fontselect.js b/app/editor/ui/fontselect.js index 97bd750d..cfec6141 100644 --- a/app/editor/ui/fontselect.js +++ b/app/editor/ui/fontselect.js @@ -23,6 +23,10 @@ goog.require('goog.ui.ControlRenderer'); goog.require('goog.ui.MenuItemRenderer'); goog.require('goog.ui.MenuSeparator'); goog.require('thin.Font'); + +goog.require('thin.ui.ComboBox'); +goog.require('thin.ui.ComboBoxItem'); + goog.require('thin.ui.Select'); goog.require('thin.ui.Option'); goog.require('thin.ui.OptionMenu'); @@ -31,21 +35,20 @@ goog.require('thin.ui.OptionMenuRenderer'); /** * @param {Array.} fonts - * @param {thin.ui.MenuButtonRenderer=} opt_renderer * @param {!thin.ui.FontOptionMenuRenderer=} opt_menuRenderer * @constructor - * @extends {thin.ui.Select} + * @extends {thin.ui.ComboBox} */ -thin.ui.FontSelect = function(fonts, opt_renderer, opt_menuRenderer) { +thin.ui.FontSelect = function(fonts, opt_menuRenderer) { var menu = new thin.ui.OptionMenu( opt_menuRenderer || thin.ui.FontOptionMenuRenderer.getInstance()); - goog.base(this, '', menu, opt_renderer); - + goog.base(this, menu); + this.addFonts(fonts); this.setValue(thin.Font.getDefaultFontFamily()); this.setTextAlignLeft(); }; -goog.inherits(thin.ui.FontSelect, thin.ui.Select); +goog.inherits(thin.ui.FontSelect, thin.ui.ComboBox); /** @inheritDoc */ @@ -62,9 +65,9 @@ thin.ui.FontSelect.prototype.addFonts = function(fonts) { goog.array.forEach(fonts, function(font) { family = font.getFamily(); - if (family == 'IPAMincho') { - this.addItem(new goog.ui.MenuSeparator()); - } + // if (family == 'IPAMincho') { + // this.addItem(new goog.ui.MenuSeparator()); + // } this.addBuiltinFont(family, font.getName()); }, this); }; @@ -85,7 +88,10 @@ thin.ui.FontSelect.prototype.addBuiltinFont = function(family, name) { * @param {string} name */ thin.ui.FontSelect.prototype.addFont = function(type, family, name) { - this.addItem(new thin.ui.FontSelectOption(type, family, name)); + var item = new thin.ui.ComboBoxItem(family); + item.setSticky(true); + this.addItem(item); + // this.addItem(new thin.ui.FontSelectOption(type, family, name)); }; @@ -101,7 +107,7 @@ thin.ui.FontSelectOption = function(type, family, name) { goog.ui.MenuItemRenderer, thin.ui.getCssName('thin-font-option')); goog.base(this, name, family, /** @type {goog.ui.MenuItemRenderer} */ (renderer)); - + this.addClassName(thin.ui.getCssName(type, 'font')); }; goog.inherits(thin.ui.FontSelectOption, thin.ui.Option); diff --git a/app/editor/ui/propertypane.js b/app/editor/ui/propertypane.js index 1c9b8bc0..12aa9460 100644 --- a/app/editor/ui/propertypane.js +++ b/app/editor/ui/propertypane.js @@ -104,7 +104,7 @@ thin.ui.PropertyPane.prototype.delay_; thin.ui.PropertyPane.prototype.createDom = function() { this.setElementInternal( this.getDomHelper().createDom('div', thin.ui.PropertyPane.CSS_CLASS)); - + goog.dom.setFocusableTabIndex(this.getElement(), true); }; @@ -130,10 +130,10 @@ thin.ui.PropertyPane.prototype.addProperty = function(property, group, opt_id) { */ thin.ui.PropertyPane.prototype.addItem = function(item, opt_id) { this.addChildWithId(item, opt_id, true); - - item.addEventListener(thin.ui.PropertyPane.AbstractItem.EventType.TARGETTING, + + item.addEventListener(thin.ui.PropertyPane.AbstractItem.EventType.TARGETTING, this.handleItemTargetting, true, this); - + if (this.selectionModel_) { this.selectionModel_.addItem(item); } else { @@ -173,7 +173,7 @@ thin.ui.PropertyPane.prototype.hasActiveControlItem = function() { * @param {goog.events.Event} e */ thin.ui.PropertyPane.prototype.handleWatchItemActivate = function(e) { - + }; @@ -201,7 +201,7 @@ thin.ui.PropertyPane.prototype.setTargettedItem = function(item) { * @return {thin.ui.PropertyPane.AbstractItem?} */ thin.ui.PropertyPane.prototype.getTargettedItem = function() { - return this.selectionModel_ ? + return this.selectionModel_ ? /** @type {thin.ui.PropertyPane.AbstractItem} */ (this.selectionModel_.getSelectedItem()) : null; @@ -217,7 +217,7 @@ thin.ui.PropertyPane.prototype.createSelectionModel_ = function() { model.addItem(child); }, this); this.selectionModel_ = model; - + model.setSelectionHandler(function(item, select) { if (item.canTargetting()) { item.setTargettedInternal(select); @@ -262,7 +262,7 @@ thin.ui.PropertyPane.prototype.getTarget = function() { thin.ui.PropertyPane.prototype.isTarget = function(target) { var currentTarget = this.target_; if (currentTarget && target) { - return goog.getUid(/** @type {Object} */ (currentTarget)) == + return goog.getUid(/** @type {Object} */ (currentTarget)) == goog.getUid(/** @type {Object} */ (target)); } return false; @@ -273,7 +273,7 @@ thin.ui.PropertyPane.prototype.clear = function() { while (this.hasChildren()) { this.removeChildAt(0, true).dispose(); } - + this.selectionModel_ && this.selectionModel_.clear(); this.target_ = null; }; @@ -284,7 +284,7 @@ thin.ui.PropertyPane.prototype.clear = function() { * @return {boolean} */ thin.ui.PropertyPane.prototype.handleKeyEvent = function(e) { - if (!this.hasActiveControlItem() && + if (!this.hasActiveControlItem() && this.getChildCount() != 0 && this.handleKeyEventInternal(e)) { e.preventDefault(); @@ -304,25 +304,25 @@ thin.ui.PropertyPane.prototype.handleKeyEventInternal = function(e) { case goog.events.KeyCodes.UP: this.changeTargetBy_(-1); break; - + case goog.events.KeyCodes.DOWN: this.changeTargetBy_(+1); break; - + case goog.events.KeyCodes.TAB: this.changeTargetBy_(e.shiftKey ? -1 : +1); break; - + case goog.events.KeyCodes.F2: case goog.events.KeyCodes.SPACE: this.handlePropertyActivateControl(e); break; - + default: return false; break; } - + return true; }; @@ -356,14 +356,14 @@ thin.ui.PropertyPane.prototype.changeTargetBy_ = function(mode) { } } else { nextItem = mode == -1 ? model.getLast() : model.getFirst(); - } + } this.setTargettedItem(/** @type {thin.ui.PropertyPane.AbstractItem} */ (nextItem)); - + if (!nextItem.canTargetting()) { this.changeTargetBy_(mode); return; } - + nextItem.getElement().focus(); } }; @@ -381,29 +381,29 @@ thin.ui.PropertyPane.prototype.getKeyHandler = function() { /** @inheritDoc */ thin.ui.PropertyPane.prototype.disposeInternal = function(){ thin.ui.PropertyPane.superClass_.disposeInternal.call(this); - + if (this.keyHandler_) { this.keyHandler_.dispose(); delete this.keyHandler_; } - + if (this.delay_) { this.delay_.dispose(); this.delay_ = null; } - + if (this.selectionModel_) { this.selectionModel_.dispose(); delete this.selectionModel_; } - + delete this.target_; }; thin.ui.PropertyPane.prototype.enterDocument = function() { thin.ui.PropertyPane.superClass_.enterDocument.call(this); - + this.getHandler(). listen(this.getKeyHandler(), goog.events.KeyHandler.EventType.KEY, this.handleKeyEvent, false, this); @@ -418,10 +418,10 @@ thin.ui.PropertyPane.prototype.enterDocument = function() { */ thin.ui.PropertyPane.AbstractItem = function(content, opt_renderer) { goog.ui.Control.call(this, content, opt_renderer); - + this.setSupportedState(goog.ui.Component.State.HOVER, false); this.setSupportedState(goog.ui.Component.State.ACTIVE, false); - + this.setHandleMouseEvents(false); }; goog.inherits(thin.ui.PropertyPane.AbstractItem, goog.ui.Control); @@ -496,7 +496,7 @@ thin.ui.PropertyPane.AbstractItem.prototype.setTargettedInternal = function(targ this.targetted_ = false; } - goog.dom.classes.enable(this.getElement(), + goog.dom.classes.enable(this.getElement(), thin.ui.getCssName(this.getRenderer().getCssClass(), 'target'), targetted); }; @@ -521,9 +521,9 @@ thin.ui.PropertyPane.AbstractItem.prototype.handleFocus = function(e) { thin.ui.PropertyPane.AbstractItem.prototype.enterDocument = function() { thin.ui.PropertyPane.AbstractItem.superClass_.enterDocument.call(this); - + this.getHandler(). - listen(this.getElement(), goog.events.EventType.FOCUS, + listen(this.getElement(), goog.events.EventType.FOCUS, this.handleFocus, false, this); }; @@ -534,14 +534,14 @@ thin.ui.PropertyPane.AbstractItem.prototype.enterDocument = function() { * @extends {thin.ui.PropertyPane.AbstractItem} */ thin.ui.PropertyPane.PropertyGroup = function(label) { - thin.ui.PropertyPane.AbstractItem.call(this, label, + thin.ui.PropertyPane.AbstractItem.call(this, label, goog.ui.ControlRenderer.getCustomRenderer( goog.ui.ControlRenderer, thin.ui.getCssName( thin.ui.PropertyPane.CSS_CLASS, 'group'))); - + this.setSupportedState(goog.ui.Component.State.OPENED, true); this.setOpen(true); - + /** * @type {Array.} * @private @@ -569,9 +569,9 @@ thin.ui.PropertyPane.PropertyGroup.prototype.removeMember = function(property) { thin.ui.PropertyPane.PropertyGroup.prototype.enterDocument = function() { thin.ui.PropertyPane.PropertyGroup.superClass_.enterDocument.call(this); - + this.getHandler(). - listen(this.getElement(), goog.events.EventType.DBLCLICK, + listen(this.getElement(), goog.events.EventType.DBLCLICK, this.handleDblClickOrSpace_, false, this); }; @@ -579,7 +579,7 @@ thin.ui.PropertyPane.PropertyGroup.prototype.enterDocument = function() { /** @inheritDoc */ thin.ui.PropertyPane.PropertyGroup.prototype.disposeInternal = function() { thin.ui.PropertyPane.PropertyGroup.superClass_.disposeInternal.call(this); - + delete this.member_; }; @@ -615,15 +615,15 @@ thin.ui.PropertyPane.PropertyGroup.prototype.handleDblClickOrSpace_ = function(e * @extends {thin.ui.PropertyPane.AbstractItem} */ thin.ui.PropertyPane.Property = function(label, control) { - thin.ui.PropertyPane.AbstractItem.call(this, label, + thin.ui.PropertyPane.AbstractItem.call(this, label, thin.ui.PropertyPane.PropertyRenderer.getInstance()); - + /** * @type {thin.ui.PropertyPane.Property.Key_} * @private */ this.keyControl_ = new thin.ui.PropertyPane.Property.Key_(label); - + /** * @type {thin.ui.PropertyPane.Property.Value_} * @private @@ -637,8 +637,8 @@ goog.inherits(thin.ui.PropertyPane.Property, thin.ui.PropertyPane.AbstractItem); * @enum {string} */ thin.ui.PropertyPane.Property.EventType = { - ACTIVE: 'active', - INACTIVE: 'inactive', + ACTIVE: 'active', + INACTIVE: 'inactive', CHANGE: 'propchange' }; @@ -681,7 +681,7 @@ thin.ui.PropertyPane.Property.prototype.getValueControl = function() { /** @inheritDoc */ thin.ui.PropertyPane.Property.prototype.createDom = function() { thin.ui.PropertyPane.Property.superClass_.createDom.call(this); - + this.addChild(this.keyControl_, true); this.addChild(this.valueCell_, true); }; @@ -711,7 +711,7 @@ thin.ui.PropertyPane.Property.prototype.setGroup = function(group) { * @param {boolean} enable */ thin.ui.PropertyPane.Property.prototype.setEnabled = function(enable) { - thin.ui.PropertyPane.Property.superClass_.setEnabled.call(this, enable); + thin.ui.PropertyPane.Property.superClass_.setEnabled.call(this, enable); this.getValueControl().setEnabled(enable); }; @@ -750,7 +750,7 @@ thin.ui.PropertyPane.Property.prototype.setControlActive = function(active) { } else { this.getParent().setActiveControlItem(null); this.getElement().focus(); - this.dispatchEvent(thin.ui.PropertyPane.Property.EventType.INACTIVE); + this.dispatchEvent(thin.ui.PropertyPane.Property.EventType.INACTIVE); } }; @@ -787,8 +787,8 @@ thin.ui.PropertyPane.Property.prototype.inactivateControlInternal = function() { thin.ui.PropertyPane.Property.prototype.dispatchPropertyChangeEvent = function() { this.dispatchEvent( new thin.ui.PropertyPane.PropertyEvent( - thin.ui.PropertyPane.Property.EventType.CHANGE, - /** @type {thin.ui.PropertyPane} */ (this.getParent()), + thin.ui.PropertyPane.Property.EventType.CHANGE, + /** @type {thin.ui.PropertyPane} */ (this.getParent()), this, this.getValueControl())); }; @@ -826,7 +826,7 @@ goog.addSingletonGetter(thin.ui.PropertyPane.PropertyRenderer); /** * @type {string} */ -thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS = +thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS = thin.ui.getCssName(thin.ui.PropertyPane.CSS_CLASS, 'prop'); @@ -841,7 +841,7 @@ thin.ui.PropertyPane.PropertyRenderer.prototype.getCssClass = function() { /** @inheritDoc */ thin.ui.PropertyPane.PropertyRenderer.prototype.createDom = function(prop) { var domHelper = prop.getDomHelper(); - return domHelper.createDom('div', this.getClassNames(prop).join(' '), + return domHelper.createDom('div', this.getClassNames(prop).join(' '), domHelper.createDom('div', thin.ui.getCssName(this.getCssClass(), 'body'))); }; @@ -862,7 +862,7 @@ thin.ui.PropertyPane.PropertyRenderer.prototype.getContentElement = function(ele */ thin.ui.PropertyPane.Property.Key_ = function(label) { goog.ui.Component.call(this); - + /** * @type {string} * @private @@ -875,8 +875,8 @@ goog.inherits(thin.ui.PropertyPane.Property.Key_, goog.ui.Component); /** @inheritDoc */ thin.ui.PropertyPane.Property.Key_.prototype.createDom = function() { thin.ui.PropertyPane.Property.Key_.superClass_.createDom.call(this); - - goog.dom.classes.add(this.getElement(), + + goog.dom.classes.add(this.getElement(), thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS + 'key')); this.setLabel(this.label_); @@ -932,10 +932,10 @@ thin.ui.PropertyPane.Property.Value_.prototype.getControl = function() { /** @inheritDoc */ thin.ui.PropertyPane.Property.Value_.prototype.createDom = function() { thin.ui.PropertyPane.Property.Value_.superClass_.createDom.call(this); - - goog.dom.classes.add(this.getElement(), + + goog.dom.classes.add(this.getElement(), thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS + 'value')); - + this.addChild(this.control_, true); }; @@ -943,7 +943,7 @@ thin.ui.PropertyPane.Property.Value_.prototype.createDom = function() { /** @inheritDoc */ thin.ui.PropertyPane.Property.Value_.prototype.disposeInternal = function() { thin.ui.PropertyPane.Property.Value_.superClass_.disposeInternal.call(this); - + this.control_ = null; }; @@ -956,17 +956,17 @@ thin.ui.PropertyPane.Property.Value_.prototype.disposeInternal = function() { */ thin.ui.PropertyPane.SelectProperty = function(label, opt_menu) { var renderer = goog.ui.ControlRenderer.getCustomRenderer( - thin.ui.MenuButtonRenderer, + thin.ui.MenuButtonRenderer, thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS, 'select')); - + var menuRenderer = goog.ui.ControlRenderer.getCustomRenderer( thin.ui.OptionMenuRenderer, thin.ui.getCssName(renderer.getCssClass(), 'optionmenu')); - var control = new thin.ui.Select(undefined, new thin.ui.OptionMenu(menuRenderer), + var control = new thin.ui.Select(undefined, new thin.ui.OptionMenu(menuRenderer), /** @type {thin.ui.MenuButtonRenderer} */ (renderer)); - + control.getMenu().setMaxHeight(200); - + thin.ui.PropertyPane.Property.call(this, label, control); }; goog.inherits(thin.ui.PropertyPane.SelectProperty, thin.ui.PropertyPane.Property); @@ -986,7 +986,7 @@ thin.ui.PropertyPane.SelectProperty.prototype.handleInactivate = function(e){ thin.ui.PropertyPane.SelectProperty.prototype.activateControlInternal = function() { this.getValueControl().setOpen(true); this.getValueControl().getElement().focus(); - + return true; }; @@ -994,16 +994,16 @@ thin.ui.PropertyPane.SelectProperty.prototype.activateControlInternal = function /** @inheritDoc */ thin.ui.PropertyPane.SelectProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.SelectProperty.superClass_.enterDocument.call(this); - + var control = this.getValueControl(); - + // For Common-Change control.addEventListener( goog.ui.Component.EventType.ACTION, this.dispatchPropertyChangeEvent, false, this); - + // For Inactive control.getMenu(). - addEventListener(goog.ui.Component.EventType.HIDE, + addEventListener(goog.ui.Component.EventType.HIDE, this.handleInactivate, false, this); }; @@ -1016,20 +1016,17 @@ thin.ui.PropertyPane.SelectProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.FontSelectProperty = function(opt_label) { var propCssClass = thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS; - var renderer = goog.ui.ControlRenderer.getCustomRenderer( - thin.ui.MenuButtonRenderer, thin.ui.getCssName(propCssClass, 'select')); var menuRenderer = goog.ui.ContainerRenderer.getCustomRenderer( thin.ui.FontOptionMenuRenderer, thin.ui.getCssName(propCssClass, 'font-selectmenu')); var control = new thin.ui.FontSelect(thin.Font.getFonts(), - /** @type {thin.ui.MenuButtonRenderer} */ (renderer), /** @type {thin.ui.FontOptionMenuRenderer} */ (menuRenderer)); control.getMenu().setMaxHeight(250); - thin.ui.PropertyPane.Property.call(this, opt_label || thin.t('field_font_family'), control); + goog.base(this, opt_label || thin.t('field_font_family'), control); }; -goog.inherits(thin.ui.PropertyPane.FontSelectProperty, thin.ui.PropertyPane.SelectProperty); +goog.inherits(thin.ui.PropertyPane.FontSelectProperty, thin.ui.PropertyPane.Property); /** @@ -1040,9 +1037,9 @@ goog.inherits(thin.ui.PropertyPane.FontSelectProperty, thin.ui.PropertyPane.Sele * @constructor */ thin.ui.PropertyPane.AbstractCheckableProperty = function(label, opt_control, opt_checked) { - var control = new goog.ui.Control(null, + var control = new goog.ui.Control(null, goog.ui.ControlRenderer.getCustomRenderer( - goog.ui.ControlRenderer, + goog.ui.ControlRenderer, thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS, 'checkable-ctl'))); control.setSupportedState(goog.ui.Component.State.HOVER, false); @@ -1112,11 +1109,11 @@ thin.ui.PropertyPane.AbstractCheckableProperty.prototype.handleInactivate = func /** @inheritDoc */ thin.ui.PropertyPane.AbstractCheckableProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.AbstractCheckableProperty.superClass_.enterDocument.call(this); - - // For Inactive by Checkbox. - this.getValueControlCheckbox().addEventListener(goog.ui.Component.EventType.CHANGE, + + // For Inactive by Checkbox. + this.getValueControlCheckbox().addEventListener(goog.ui.Component.EventType.CHANGE, this.handleInactivate, true, this); - + // For Common-Change by Checkbox. this.getValueControl().addEventListener( goog.ui.Component.EventType.CHANGE, this.dispatchPropertyChangeEvent, false, this); @@ -1135,7 +1132,7 @@ thin.ui.PropertyPane.CheckableInputProperty = function(label, opt_label, opt_che thin.ui.PropertyPane.AbstractCheckableProperty.call(this, label, control, opt_checked); }; -goog.inherits(thin.ui.PropertyPane.CheckableInputProperty, +goog.inherits(thin.ui.PropertyPane.CheckableInputProperty, thin.ui.PropertyPane.AbstractCheckableProperty); @@ -1148,7 +1145,7 @@ thin.ui.PropertyPane.CheckableInputProperty.prototype.activateControlInternal = this.getValueControlCheckbox().dispatchEvent( goog.ui.Component.EventType.CHANGE); } - + goog.dom.forms.focusAndSelect(this.getValueControlMain().getElement()); return true; @@ -1195,22 +1192,22 @@ thin.ui.PropertyPane.CheckableInputProperty.prototype.handleClickInput = functio /** @inheritDoc */ thin.ui.PropertyPane.CheckableInputProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.CheckableInputProperty.superClass_.enterDocument.call(this); - + var inputControl = this.getValueControlMain(); - + // For Common-Change by Input(MainControl). inputControl.addEventListener( goog.ui.Component.EventType.CHANGE, this.dispatchPropertyChangeEvent, false, this); - + // For Inactive by Input(MainControl). - goog.events.listen(inputControl, - [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + goog.events.listen(inputControl, + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], this.handleInactivate, false, this); - + // For Click Active by Input(MainControl). goog.events.listen(inputControl.getElement(), goog.events.EventType.CLICK, this.handleClickInput, false, this); - + // For Click Active by Checkbox(CheckboxControl). goog.events.listen(this.getValueControlCheckbox().getElement(), goog.events.EventType.CLICK, this.handleClickCheck, false, this); @@ -1243,7 +1240,7 @@ thin.ui.PropertyPane.InputProperty.prototype.handleInactivate = function(e){ */ thin.ui.PropertyPane.InputProperty.prototype.activateControlInternal = function() { goog.dom.forms.focusAndSelect(this.getValueControl().getElement()); - + return true; }; @@ -1251,18 +1248,18 @@ thin.ui.PropertyPane.InputProperty.prototype.activateControlInternal = function( /** @inheritDoc */ thin.ui.PropertyPane.InputProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.InputProperty.superClass_.enterDocument.call(this); - + var control = this.getValueControl(); - + // For Common-Change control.addEventListener( goog.ui.Component.EventType.CHANGE, this.dispatchPropertyChangeEvent, false, this); - + // For Active/Inactive - goog.events.listen(control, - [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + goog.events.listen(control, + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], this.handleInactivate, false, this); - + // For Click Active goog.events.listen(control.getElement(), goog.events.EventType.CLICK, this.handleClick, false, this); @@ -1301,18 +1298,18 @@ thin.ui.PropertyPane.NumberInputProperty.prototype.activateControlInternal = fun /** @inheritDoc */ thin.ui.PropertyPane.NumberInputProperty.prototype.enterDocument = function() { goog.base(this, 'enterDocument'); - + var control = this.getValueControl().getInput(); - + // For Common-Change control.addEventListener( goog.ui.Component.EventType.CHANGE, this.dispatchPropertyChangeEvent, false, this); - + // For Active/Inactive - goog.events.listen(control, - [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + goog.events.listen(control, + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], this.handleInactivate, false, this); - + // For Click Active goog.events.listen(control.getElement(), goog.events.EventType.CLICK, this.handleClick, false, this); @@ -1328,12 +1325,12 @@ thin.ui.PropertyPane.NumberInputProperty.prototype.enterDocument = function() { */ thin.ui.PropertyPane.IdInputProperty = function(target, label, opt_label) { goog.base(this, label, opt_label); - + var control = this.getValueControl(); var validator = new thin.ui.PropertyPane.IdInputProperty.Validator_(control); validator.setShape(target); control.setValidator(validator); - + /** * @type {thin.ui.PropertyPane.IdInputProperty.Validator_} * @private @@ -1355,7 +1352,7 @@ thin.ui.PropertyPane.IdInputProperty.prototype.getIdValidator = function() { /** @inheritDoc */ thin.ui.PropertyPane.IdInputProperty.prototype.disposeInternal = function() { goog.base(this, 'disposeInternal'); - + delete this.idValidator_; }; @@ -1367,7 +1364,7 @@ thin.ui.PropertyPane.IdInputProperty.prototype.disposeInternal = function() { */ thin.ui.PropertyPane.IdInputProperty.Validator_ = function(opt_target) { goog.base(this, opt_target); - + this.setValidatePresence(this.validatePresence_); this.setMethod(this.validate_); }; @@ -1452,7 +1449,7 @@ thin.ui.PropertyPane.IdInputProperty.Validator_.prototype.validate_ = function(v /** @inheritDoc */ thin.ui.PropertyPane.IdInputProperty.Validator_.prototype.disposeInternal = function() { goog.base(this, 'disposeInternal'); - + this.shape_ = null; }; @@ -1466,7 +1463,7 @@ thin.ui.PropertyPane.IdInputProperty.Validator_.prototype.disposeInternal = func thin.ui.PropertyPane.ComboBoxProperty = function(label, opt_menu) { var control = thin.ui.ComboBox.getCustomComboBox( thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS, 'combobox'), opt_menu); - + thin.ui.PropertyPane.Property.call(this, label, control); }; goog.inherits(thin.ui.PropertyPane.ComboBoxProperty, thin.ui.PropertyPane.Property); @@ -1497,7 +1494,7 @@ thin.ui.PropertyPane.ComboBoxProperty.prototype.activateControlInternal = functi /** @inheritDoc */ thin.ui.PropertyPane.ComboBoxProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.ComboBoxProperty.superClass_.enterDocument.call(this); - + var control = this.getValueControl(); // For Common-Change @@ -1505,10 +1502,10 @@ thin.ui.PropertyPane.ComboBoxProperty.prototype.enterDocument = function() { goog.ui.Component.EventType.CHANGE, this.dispatchPropertyChangeEvent, false, this); // For Active/Inactive - goog.events.listen(control.getInput(), - [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + goog.events.listen(control.getInput(), + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], this.handleInactivate, false, this); - + // For Click Active goog.events.listen(control.getInput().getElement(), goog.events.EventType.CLICK, this.handleClick, false, this); @@ -1525,7 +1522,7 @@ thin.ui.PropertyPane.ComboBoxProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.CheckboxProperty = function(label, opt_label, opt_checked) { var control = new thin.ui.Checkbox(opt_label || '', opt_checked); control.setSupportedState(goog.ui.Component.State.FOCUSED, false); - + thin.ui.PropertyPane.Property.call(this, label, control); }; goog.inherits(thin.ui.PropertyPane.CheckboxProperty, thin.ui.PropertyPane.Property); @@ -1537,7 +1534,7 @@ goog.inherits(thin.ui.PropertyPane.CheckboxProperty, thin.ui.PropertyPane.Proper thin.ui.PropertyPane.CheckboxProperty.prototype.activateControlInternal = function() { this.getValueControl().toggle(); this.dispatchPropertyChangeEvent(); - + return false; }; @@ -1558,7 +1555,7 @@ thin.ui.PropertyPane.CheckboxProperty.prototype.handleClick = function(e) { /** @inheritDoc */ thin.ui.PropertyPane.CheckboxProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.CheckboxProperty.superClass_.enterDocument.call(this); - + // For Click Active and Common-Change goog.events.listen(this.getValueControl().getElement(), goog.events.EventType.CLICK, this.handleClick, false, this); @@ -1573,7 +1570,7 @@ thin.ui.PropertyPane.CheckboxProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.ColorProperty = function(label) { var control = new thin.ui.InputColorPicker( /** @type {thin.ui.InputColorPickerRenderer} */ ( - goog.ui.ControlRenderer.getCustomRenderer(thin.ui.InputColorPickerRenderer, + goog.ui.ControlRenderer.getCustomRenderer(thin.ui.InputColorPickerRenderer, thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS, 'color')))); thin.ui.PropertyPane.Property.call(this, label, control); @@ -1603,33 +1600,33 @@ thin.ui.PropertyPane.ColorProperty.prototype.handleInactivate = function(e) { /** @inheritDoc */ thin.ui.PropertyPane.ColorProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.ColorProperty.superClass_.enterDocument.call(this); - + var control = this.getValueControl(); - + // For Common-Change control.addEventListener( goog.ui.Component.EventType.CHANGE, this.dispatchPropertyChangeEvent, false, this); - + // For Active/Inactive control.addEventListener( goog.ui.Component.EventType.ACTION, this.handleInactivate, false, this); - goog.events.listen(control, - [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + goog.events.listen(control, + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], this.handleInactivate, false, this); var colorMenuButton = control.getButton(); var colorMenu = colorMenuButton.getMenu(); colorMenu. - addEventListener(goog.ui.Component.EventType.SHOW, + addEventListener(goog.ui.Component.EventType.SHOW, function(e) { if(!colorMenuButton.isFocused()) { colorMenuButton.getElement().focus(); } }, false, this); colorMenu. - addEventListener(goog.ui.Component.EventType.HIDE, + addEventListener(goog.ui.Component.EventType.HIDE, this.handleInactivate, false, this); - + // For Click Active goog.events.listen(control.getInput().getElement(), goog.events.EventType.CLICK, this.handleClick, false, this); diff --git a/app/editor/ui/toolbar.js b/app/editor/ui/toolbar.js index d9f8dba1..d2b17047 100644 --- a/app/editor/ui/toolbar.js +++ b/app/editor/ui/toolbar.js @@ -72,7 +72,7 @@ thin.ui.Toolbar.CSS_CLASS = thin.ui.getCssName('thin-toolbar'); thin.ui.Toolbar.prototype.setupChild = function(id, child, renderTo, opt_setupHandler) { thin.ui.Toolbar.superClass_.setupChild.call(this, child, id, opt_setupHandler, false); child.render(renderTo); - + return child; }; @@ -85,7 +85,7 @@ thin.ui.Toolbar.prototype.setupChild = function(id, child, renderTo, opt_setupHa * @extends {thin.ui.Button} */ thin.ui.ToolbarButton = function(content, opt_icon, opt_renderer) { - thin.ui.Button.call(this, content, opt_icon, + thin.ui.Button.call(this, content, opt_icon, /** @type {thin.ui.ButtonRenderer} */ (opt_renderer || goog.ui.ControlRenderer.getCustomRenderer( thin.ui.ButtonRenderer, thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'button')))); @@ -101,10 +101,10 @@ goog.inherits(thin.ui.ToolbarButton, thin.ui.Button); * @extends {thin.ui.ToggleButton} */ thin.ui.ToolbarToggleButton = function(content, opt_icon, opt_renderer) { - thin.ui.ToggleButton.call(this, content, opt_icon, - /** @type {thin.ui.ButtonRenderer} */ (opt_renderer || + thin.ui.ToggleButton.call(this, content, opt_icon, + /** @type {thin.ui.ButtonRenderer} */ (opt_renderer || goog.ui.ControlRenderer.getCustomRenderer( - thin.ui.ButtonRenderer, + thin.ui.ButtonRenderer, thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'button')))); }; goog.inherits(thin.ui.ToolbarToggleButton, thin.ui.ToggleButton); @@ -116,10 +116,10 @@ goog.inherits(thin.ui.ToolbarToggleButton, thin.ui.ToggleButton); * @extends {thin.ui.IconButton} */ thin.ui.ToolbarIconButton = function(icon) { - thin.ui.IconButton.call(this, icon, + thin.ui.IconButton.call(this, icon, /** @type {thin.ui.ButtonRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( - thin.ui.ButtonRenderer, + thin.ui.ButtonRenderer, thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'button')))); }; goog.inherits(thin.ui.ToolbarIconButton, thin.ui.IconButton); @@ -131,10 +131,10 @@ goog.inherits(thin.ui.ToolbarIconButton, thin.ui.IconButton); * @extends {thin.ui.ToggleIconButton} */ thin.ui.ToolbarToggleIconButton = function(icon) { - thin.ui.ToggleIconButton.call(this, icon, + thin.ui.ToggleIconButton.call(this, icon, /** @type {thin.ui.ButtonRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( - thin.ui.ButtonRenderer, + thin.ui.ButtonRenderer, thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'button')))); }; goog.inherits(thin.ui.ToolbarToggleIconButton, thin.ui.ToggleIconButton); @@ -148,7 +148,7 @@ goog.inherits(thin.ui.ToolbarToggleIconButton, thin.ui.ToggleIconButton); * @extends {thin.ui.MenuButton} */ thin.ui.ToolbarMenuButton = function(content, opt_icon, opt_menu) { - thin.ui.MenuButton.call(this, content, opt_icon, opt_menu, + thin.ui.MenuButton.call(this, content, opt_icon, opt_menu, /** @type {thin.ui.MenuButtonRenderer} */( goog.ui.ControlRenderer.getCustomRenderer( thin.ui.MenuButtonRenderer, thin.ui.getCssName( @@ -166,23 +166,23 @@ goog.inherits(thin.ui.ToolbarMenuButton, thin.ui.MenuButton); */ thin.ui.ToolbarSplitButton = function(content, opt_icon, opt_orientation) { var cssClass = thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'split-button'); - - thin.ui.SplitButton.call(this, content, opt_icon, opt_orientation, + + thin.ui.SplitButton.call(this, content, opt_icon, opt_orientation, /** @type {thin.ui.SplitButtonRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( thin.ui.SplitButtonRenderer, thin.ui.getCssName(cssClass)))); - + /** @inheritDoc */ - this.button_ = new thin.ui.ToolbarButton(content, opt_icon, + this.button_ = new thin.ui.ToolbarButton(content, opt_icon, /** @type {thin.ui.ButtonRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( thin.ui.ButtonRenderer, thin.ui.getCssName(cssClass, 'button')))); /** @inheritDoc */ this.handle_ = new thin.ui.ToolbarSplitButton.Handle(); - + /** @inheritDoc */ - this.orientation_ = opt_orientation || + this.orientation_ = opt_orientation || thin.ui.SplitButton.Orientation.HORIZONTAL; }; goog.inherits(thin.ui.ToolbarSplitButton, thin.ui.SplitButton); @@ -193,8 +193,8 @@ goog.inherits(thin.ui.ToolbarSplitButton, thin.ui.SplitButton); * @extends {thin.ui.SplitButton.Handle} */ thin.ui.ToolbarSplitButton.Handle = function() { - thin.ui.SplitButton.Handle.call(this, - /** @type {thin.ui.SplitButtonHandleRenderer} */ ( + thin.ui.SplitButton.Handle.call(this, + /** @type {thin.ui.SplitButtonHandleRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( thin.ui.SplitButtonHandleRenderer, thin.ui.getCssName( thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'split-button'), 'handle')))); @@ -211,14 +211,14 @@ goog.inherits(thin.ui.ToolbarSplitButton.Handle, thin.ui.SplitButton.Handle); */ thin.ui.ToolbarSplitToggleButton = function(content, opt_icon, opt_orientation) { var cssClass = thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'split-button'); - - thin.ui.SplitToggleButton.call(this, content, opt_icon, opt_orientation, + + thin.ui.SplitToggleButton.call(this, content, opt_icon, opt_orientation, /** @type {thin.ui.SplitButtonRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( thin.ui.SplitButtonRenderer, thin.ui.getCssName(cssClass)))); - + /** @inheritDoc */ - this.button_ = new thin.ui.ToolbarToggleButton(content, opt_icon, + this.button_ = new thin.ui.ToolbarToggleButton(content, opt_icon, /** @type {thin.ui.ButtonRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( thin.ui.ButtonRenderer, thin.ui.getCssName( @@ -250,7 +250,7 @@ goog.inherits(thin.ui.ToolbarSelect, thin.ui.Select); */ thin.ui.ToolbarFontSelect = function() { thin.ui.FontSelect.call(this, thin.Font.getFonts()); - this.addClassName(thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'select')); + // this.addClassName(thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'select')); }; goog.inherits(thin.ui.ToolbarFontSelect, thin.ui.FontSelect); @@ -261,10 +261,10 @@ goog.inherits(thin.ui.ToolbarFontSelect, thin.ui.FontSelect); * @extends {goog.ui.Separator} */ thin.ui.ToolbarSeparator = function(opt_renderer) { - goog.ui.Separator.call(this, - /** @type {goog.ui.MenuSeparatorRenderer} */(opt_renderer || + goog.ui.Separator.call(this, + /** @type {goog.ui.MenuSeparatorRenderer} */(opt_renderer || goog.ui.ControlRenderer.getCustomRenderer( - goog.ui.ControlRenderer, + goog.ui.ControlRenderer, thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'separator')))); }; goog.inherits(thin.ui.ToolbarSeparator, goog.ui.Separator); From 657d264c8300fe70bd9dbd72ff0d41fe81ca10c9 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Tue, 20 Mar 2018 03:15:21 +0900 Subject: [PATCH 02/28] Fix UI for FontFamilyProperty --- app/editor/ui/propertypane.js | 70 +++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/app/editor/ui/propertypane.js b/app/editor/ui/propertypane.js index 12aa9460..a9c0901b 100644 --- a/app/editor/ui/propertypane.js +++ b/app/editor/ui/propertypane.js @@ -1008,27 +1008,6 @@ thin.ui.PropertyPane.SelectProperty.prototype.enterDocument = function() { }; -/** - * @param {string=} opt_label - * @constructor - * @extends {thin.ui.PropertyPane.SelectProperty} - */ -thin.ui.PropertyPane.FontSelectProperty = function(opt_label) { - var propCssClass = thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS; - - var menuRenderer = goog.ui.ContainerRenderer.getCustomRenderer( - thin.ui.FontOptionMenuRenderer, thin.ui.getCssName(propCssClass, 'font-selectmenu')); - - var control = new thin.ui.FontSelect(thin.Font.getFonts(), - /** @type {thin.ui.FontOptionMenuRenderer} */ (menuRenderer)); - - control.getMenu().setMaxHeight(250); - - goog.base(this, opt_label || thin.t('field_font_family'), control); -}; -goog.inherits(thin.ui.PropertyPane.FontSelectProperty, thin.ui.PropertyPane.Property); - - /** * @param {string} label * @param {goog.ui.Component=} opt_control @@ -1457,17 +1436,39 @@ thin.ui.PropertyPane.IdInputProperty.Validator_.prototype.disposeInternal = func /** * @param {string} label * @param {thin.ui.OptionMenu=} opt_menu + * @param {thin.ui.ComboBox=} opt_control * @constructor * @extends {thin.ui.PropertyPane.Property} */ -thin.ui.PropertyPane.ComboBoxProperty = function(label, opt_menu) { - var control = thin.ui.ComboBox.getCustomComboBox( - thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS, 'combobox'), opt_menu); +thin.ui.PropertyPane.ComboBoxProperty = function(label, opt_menu, opt_control) { + var cssClass = thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS, 'combobox'); + var control; + + if (opt_control) { + control = thin.ui.PropertyPane.ComboBoxProperty.buildCustomControl(cssClass, opt_control); + } else { + control = thin.ui.ComboBox.getCustomComboBox(cssClass, opt_menu); + } thin.ui.PropertyPane.Property.call(this, label, control); }; goog.inherits(thin.ui.PropertyPane.ComboBoxProperty, thin.ui.PropertyPane.Property); +/** + * @param {string} cssClass + * @param {thin.ui.ComboBox} control + * @return {thin.ui.ComboBox} + */ +thin.ui.PropertyPane.ComboBoxProperty.buildCustomControl = function (cssClass, control) { + /** + * @return {string} + */ + control.getCssClass = function () { + return cssClass; + } + return control; +}; + /** * @param {goog.events.Event} e @@ -1512,6 +1513,27 @@ thin.ui.PropertyPane.ComboBoxProperty.prototype.enterDocument = function() { }; +/** + * @param {string=} opt_label + * @constructor + * @extends {thin.ui.PropertyPane.ComboBoxProperty} + */ +thin.ui.PropertyPane.FontSelectProperty = function(opt_label) { + var propCssClass = thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS; + + var menuRenderer = goog.ui.ContainerRenderer.getCustomRenderer( + thin.ui.FontOptionMenuRenderer, thin.ui.getCssName(propCssClass, 'font-selectmenu')); + + var control = new thin.ui.FontSelect(thin.Font.getFonts(), + /** @type {thin.ui.FontOptionMenuRenderer} */ (menuRenderer)); + + control.getMenu().setMaxHeight(250); + + goog.base(this, opt_label || thin.t('field_font_family'), null, control); +}; +goog.inherits(thin.ui.PropertyPane.FontSelectProperty, thin.ui.PropertyPane.ComboBoxProperty); + + /** * @param {string} label * @param {string=} opt_label From 57fcb3605c4e8e6fa70f02779c4e0fd83fbc6954 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Tue, 20 Mar 2018 03:33:51 +0900 Subject: [PATCH 03/28] Refactor --- app/editor/ui/fontselect.js | 58 +++---------------------------------- 1 file changed, 4 insertions(+), 54 deletions(-) diff --git a/app/editor/ui/fontselect.js b/app/editor/ui/fontselect.js index cfec6141..11b8f9a5 100644 --- a/app/editor/ui/fontselect.js +++ b/app/editor/ui/fontselect.js @@ -14,21 +14,15 @@ // along with this program. If not, see . goog.provide('thin.ui.FontSelect'); -goog.provide('thin.ui.FontSelectOption'); goog.provide('thin.ui.FontOptionMenuRenderer'); goog.require('goog.array'); goog.require('goog.style'); -goog.require('goog.ui.ControlRenderer'); -goog.require('goog.ui.MenuItemRenderer'); -goog.require('goog.ui.MenuSeparator'); goog.require('thin.Font'); goog.require('thin.ui.ComboBox'); goog.require('thin.ui.ComboBoxItem'); -goog.require('thin.ui.Select'); -goog.require('thin.ui.Option'); goog.require('thin.ui.OptionMenu'); goog.require('thin.ui.OptionMenuRenderer'); @@ -61,63 +55,19 @@ thin.ui.FontSelect.prototype.setValue = function(name) { * @param {Array.} fonts */ thin.ui.FontSelect.prototype.addFonts = function(fonts) { - var family; - goog.array.forEach(fonts, function(font) { - family = font.getFamily(); - // if (family == 'IPAMincho') { - // this.addItem(new goog.ui.MenuSeparator()); - // } - this.addBuiltinFont(family, font.getName()); + this.addFont(font); }, this); }; /** - * @param {string} family - * @param {string} name + * @param {thin.Font} font */ -thin.ui.FontSelect.prototype.addBuiltinFont = function(family, name) { - this.addFont(thin.ui.FontSelectOption.Type.BUILTIN, family, name); -}; - - -/** - * @param {thin.ui.FontSelectOption.Type} type - * @param {string} family - * @param {string} name - */ -thin.ui.FontSelect.prototype.addFont = function(type, family, name) { - var item = new thin.ui.ComboBoxItem(family); +thin.ui.FontSelect.prototype.addFont = function(font) { + var item = new thin.ui.ComboBoxItem(font.getFamily()); item.setSticky(true); this.addItem(item); - // this.addItem(new thin.ui.FontSelectOption(type, family, name)); -}; - - -/** - * @param {thin.ui.FontSelectOption.Type} type - * @param {string} family - * @param {goog.ui.ControlContent} name - * @constructor - * @extends {thin.ui.Option} - */ -thin.ui.FontSelectOption = function(type, family, name) { - var renderer = goog.ui.ControlRenderer.getCustomRenderer( - goog.ui.MenuItemRenderer, thin.ui.getCssName('thin-font-option')); - goog.base(this, name, family, - /** @type {goog.ui.MenuItemRenderer} */ (renderer)); - - this.addClassName(thin.ui.getCssName(type, 'font')); -}; -goog.inherits(thin.ui.FontSelectOption, thin.ui.Option); - - -/** - * @enum {string} - */ -thin.ui.FontSelectOption.Type = { - BUILTIN: 'builtin' }; From 13944111b29c23185532314f3513694a0c7d57f5 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Thu, 22 Mar 2018 01:09:48 +0900 Subject: [PATCH 04/28] Check the specified family is a valid font --- app/assets/css-files.yml | 7 ++- app/assets/fontvalidator.css | 15 +++++ app/editor/base/font.js | 14 +++++ app/editor/base/platform/fontvalidator.js | 68 +++++++++++++++++++++++ app/editor/ui/fontselect.js | 25 +++++++++ app/index.html | 2 + app/locales/en.js | 1 + app/locales/ja.js | 2 + app/locales/pt-BR.js | 1 + 9 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 app/assets/fontvalidator.css create mode 100644 app/editor/base/platform/fontvalidator.js diff --git a/app/assets/css-files.yml b/app/assets/css-files.yml index 4d934646..cb4c1d31 100644 --- a/app/assets/css-files.yml +++ b/app/assets/css-files.yml @@ -1,15 +1,15 @@ # Copyright (C) 2012 Matsukei Co.,Ltd. -# +# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program. If not, see . @@ -43,3 +43,4 @@ - toolbox.css - view.css - workspace.css +- fontvalidator.css diff --git a/app/assets/fontvalidator.css b/app/assets/fontvalidator.css new file mode 100644 index 00000000..0ce07dd6 --- /dev/null +++ b/app/assets/fontvalidator.css @@ -0,0 +1,15 @@ +@font-face { + font-family: AdobeBlank; + src: + url("data:font/opentype;base64,T1RUTwAKAIAAAwAgQ0ZGIDTeCDQAACFkAAAZPERTSUcAAAABAABKqAAAAAhPUy8yAF+xmwAAARAAAABgY21hcCRDbtEAAAdcAAAZ6GhlYWQFl9tDAAAArAAAADZoaGVhB1oD7wAAAOQAAAAkaG10eAPoAHwAADqgAAAQBm1heHAIAVAAAAABCAAAAAZuYW1lIE0HkgAAAXAAAAXrcG9zdP+4ADIAACFEAAAAIAABAAAAAQuFfcPHtV8PPPUAAwPoAAAAANFMRfMAAAAA0UxF8wB8/4gDbANwAAAAAwACAAAAAAAAAAEAAANw/4gAAAPoAHwAfANsAAEAAAAAAAAAAAAAAAAAAAACAABQAAgBAAAAAwPoAZAABQAAAooCWAAAAEsCigJYAAABXgAyANwAAAAAAAAAAAAAAAD3/67/+9///w/gAD8AAAAAQURCTwBAAAD//wNw/4gAAANwAHhgLwH/AAAAAAAAAAAAAAAgAAAAAAARANIAAQAAAAAAAQALAAAAAQAAAAAAAgAHAAsAAQAAAAAAAwAbABIAAQAAAAAABAALAAAAAQAAAAAABQA6AC0AAQAAAAAABgAKAGcAAwABBAkAAACUAHEAAwABBAkAAQAWAQUAAwABBAkAAgAOARsAAwABBAkAAwA2ASkAAwABBAkABAAWAQUAAwABBAkABQB0AV8AAwABBAkABgAUAdMAAwABBAkACAA0AecAAwABBAkACwA0AhsAAwABBAkADQKWAk8AAwABBAkADgA0BOVBZG9iZSBCbGFua1JlZ3VsYXIxLjA0NTtBREJPO0Fkb2JlQmxhbms7QURPQkVWZXJzaW9uIDEuMDQ1O1BTIDEuMDQ1O2hvdGNvbnYgMS4wLjgyO21ha2VvdGYubGliMi41LjYzNDA2QWRvYmVCbGFuawBDAG8AcAB5AHIAaQBnAGgAdAAgAKkAIAAyADAAMQAzACwAIAAyADAAMQA1ACAAQQBkAG8AYgBlACAAUwB5AHMAdABlAG0AcwAgAEkAbgBjAG8AcgBwAG8AcgBhAHQAZQBkACAAKABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBkAG8AYgBlAC4AYwBvAG0ALwApAC4AQQBkAG8AYgBlACAAQgBsAGEAbgBrAFIAZQBnAHUAbABhAHIAMQAuADAANAA1ADsAQQBEAEIATwA7AEEAZABvAGIAZQBCAGwAYQBuAGsAOwBBAEQATwBCAEUAVgBlAHIAcwBpAG8AbgAgADEALgAwADQANQA7AFAAUwAgADEALgAwADQANQA7AGgAbwB0AGMAbwBuAHYAIAAxAC4AMAAuADgAMgA7AG0AYQBrAGUAbwB0AGYALgBsAGkAYgAyAC4ANQAuADYAMwA0ADAANgBBAGQAbwBiAGUAQgBsAGEAbgBrAEEAZABvAGIAZQAgAFMAeQBzAHQAZQBtAHMAIABJAG4AYwBvAHIAcABvAHIAYQB0AGUAZABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBkAG8AYgBlAC4AYwBvAG0ALwB0AHkAcABlAC8AVABoAGkAcwAgAEYAbwBuAHQAIABTAG8AZgB0AHcAYQByAGUAIABpAHMAIABsAGkAYwBlAG4AcwBlAGQAIAB1AG4AZABlAHIAIAB0AGgAZQAgAFMASQBMACAATwBwAGUAbgAgAEYAbwBuAHQAIABMAGkAYwBlAG4AcwBlACwAIABWAGUAcgBzAGkAbwBuACAAMQAuADEALgAgAFQAaABpAHMAIABGAG8AbgB0ACAAUwBvAGYAdAB3AGEAcgBlACAAaQBzACAAZABpAHMAdAByAGkAYgB1AHQAZQBkACAAbwBuACAAYQBuACAAIgBBAFMAIABJAFMAIgAgAEIAQQBTAEkAUwAsACAAVwBJAFQASABPAFUAVAAgAFcAQQBSAFIAQQBOAFQASQBFAFMAIABPAFIAIABDAE8ATgBEAEkAVABJAE8ATgBTACAATwBGACAAQQBOAFkAIABLAEkATgBEACwAIABlAGkAdABoAGUAcgAgAGUAeABwAHIAZQBzAHMAIABvAHIAIABpAG0AcABsAGkAZQBkAC4AIABTAGUAZQAgAHQAaABlACAAUwBJAEwAIABPAHAAZQBuACAARgBvAG4AdAAgAEwAaQBjAGUAbgBzAGUAIABmAG8AcgAgAHQAaABlACAAcwBwAGUAYwBpAGYAaQBjACAAbABhAG4AZwB1AGEAZwBlACwAIABwAGUAcgBtAGkAcwBzAGkAbwBuAHMAIABhAG4AZAAgAGwAaQBtAGkAdABhAHQAaQBvAG4AcwAgAGcAbwB2AGUAcgBuAGkAbgBnACAAeQBvAHUAcgAgAHUAcwBlACAAbwBmACAAdABoAGkA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wwDEAMUAxgDHAMgAyQDKAMsAzADNAM4AzwDQANEA0gDTANQA1QDWANcA2ADZANoA2wDcAN0A3gDfAOAA4QDiAOMA5ADlAOYA5wDoAOkA6gDrAOwA7QDuAO8A8ADxAPIA8wD0APUA9gD3APgA+QD6APsA/AD9AP4A/wEAAQEBAgEDAQQBBQEGAQcBCAEJAQoBCwEMAQ0BDgEPARABEQESARMBFAEVARYBFwEYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBKQEqASsBLAEtAS4BLwEwATEBMgEzATQBNQE2ATcBOAE5AToBOwE8AT0BPgE/AUABQQFCAUMBRAFFAUYBRwFIAUkBSgFLAUwBTQFOAU8BUAFRAVIBUwFUAVUBVgFXAVgBWQFaAVsBXAFdAV4BXwFgAWEBYgFjAWQBZQFmAWcBaAFpAWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+AX8BgAGBAYIBgwGEAYUBhgGHAYgBiQGKAYsBjAGNAY4BjwGQAZEBkgGTAZQBlQGWAZcBmAGZAZoBmwGcAZ0BngGfAaABoQGiAaMBpAGlAaYBpwGoAakBqgGrAawBrQGuAa8BsAGxAbIBswG0AbUBtgG3AbgBuQG6AbsBvAG9Ab4BvwHAAcEBwgHDAcQBxQHGAccByAHJAcoBywHMAc0BzgHPAdAB0QHSAdMB1AHVAdYB1wHYAdkB2gHbAdwB3QHeAd8B4AHhAeIB4wHkAeUB5gHnAegB6QHqAesB7AHtAe4B7wHwAfEB8gHzAfQB9QH2AfcB+AH5AfoB+wH8Af0B/gH/AgACAQICAgMCBAIFAgYCBwIIAgkCCgILAgwCDQIOAg8CEAIRAhICEwIUAhUCFgIXAhgCGQIaAhsCHAIdAh4CHwIgAiECIgIjAiQCJQImAicCKAIpAioCKwIsAi0CLgIvAjACMQIyAjMCNAI1AjYCNwI4AjkCOgI7AjwCPQI+Aj8CQAJBAkICQwJEAkUCRgJHAkgCSQJKAksCTAJNAk4CTwJQAlECUgJTAlQCVQJWAlcCWAJZAloCWwJcAl0CXgJfAmACYQJiAmMCZAJlAmYCZwJoAmkCagJrAmwCbQJuAm8CcAJxAnICcwJ0AnUCdgJ3AngCeQJ6AnsCfAJ9An4CfwKAAoECggKDAoQChQKGAocCiAKJAooCiwKMAo0CjgKPApACkQKSApMClAKVApYClwKYApkCmgKbApwCnQKeAp8CoAKhAqICowKkAqUCpgKnAqgCqQKqAqsCrAKtAq4CrwKwArECsgKzArQCtQK2ArcCuAK5AroCuwK8Ar0CvgK/AsACwQLCAsMCxALFAsYCxwLIAskCygLLAswCzQLOAs8C0ALRAtIC0wLUAtUC1gLXAtgC2QLaAtsC3ALdAt4C3wLgAuEC4gLjAuQC5QLmAucC6ALpAuoC6wLsAu0C7gLvAvAC8QLyAvMC9AL1AvYC9wL4AvkC+gL7AvwC/QL+Av8DAAMBAwIDAwMEAwUDBgMHAwgDCQMKAwsDDAMNAw4DDwMQAxEDEgMTAxQDFQMWAxcDGAMZAxoDGwMcAx0DHgMfAyADIQMiAyMDJAMlAyYDJwMoAykDKgMrAywDLQMuAy8DMAMxAzIDMwM0AzUDNgM3AzgDOQM6AzsDPAM9Az4DPwNAA0EDQgNDA0QDRQNGA0cDSANJA0oDSwNMA00DTgNPA1ADUQNSA1MDVANVA1YDVwNYA1kDWgNbA1wDXQNeA18DYANhA2IDYwNkA2UDZgNnA2gDaQNqA2sDbANtA24DbwNwA3EDcgNzA3QDdQN2A3cDeAN5A3oDewN8A30DfgN/A4ADgQOCA4MDhAOFA4YDhwOIA4kDigOLA4wDjQOOA48DkAORA5IDkwOUA5UDlgOXA5gDmQOaA5sDnAOdA54DnwOgA6EDogOjA6QDpQOmA6cDqAOpA6oDqwOsA60DrgOvA7ADsQOyA7MDtAO1A7YDtwO4A7kDugO7A7wDvQO+A78DwAPBA8IDwwPEA8UDxgPHA8gDyQPKA8sDzAPNA84DzwPQA9ED0gPTA9QD1QPWA9cD2APZA9oD2wPcA90D3gPfA+AD4QPiA+MD5APlA+YD5wPoA+kD6gPrA+wD7QPuA+8D8APxA/ID8wP0A/UD9gP3A/gD+QP6A/sD/AP9A/4D/wQABAEEAgQDBAQEBQQGBAcECAQJBAoECwQMBA0EDgQPBBAEEQQSBBMEFAQVBBYEFwQYBBkEGgQbBBwEHQQeBB8EIAQhBCIEIwQkBCUEJgQnBCgEKQQqBCsELAQtBC4ELwQwBDEEMgQzBDQENQQ2BDcEOAQ5BDoEOwQ8BD0EPgQ/BEAEQQRCBEMERARFBEYERwRIBEkESgRLBEwETQROBE8EUARRBFIEUwRUBFUEVgRXBFgEWQRaBFsEXARdBF4EXwRgBGEEYgRjBGQEZQRmBGcEaARpBGoEawRsBG0EbgRvBHAEcQRyBHMEdAR1BHYEdwR4BHkEegR7BHwEfQR+BH8EgASBBIIEgwSEBIUEhgSHBIgEiQSKBIsEjASNBI4EjwSQBJEEkgSTBJQElQSWBJcEmASZBJoEmwScBJ0EngSfBKAEoQSiBKMEpASlBKYEpwSoBKkEqgSrBKwErQSuBK8EsASxBLIEswS0BLUEtgS3BLgEuQS6BLsEvAS9BL4EvwTABMEEwgTDBMQExQTGBMcEyATJBMoEywTMBM0EzgTPBNAE0QTSBNME1ATVBNYE1wTYBNkE2gTbBNwE3QTeBN8E4AThBOIE4wTkBOUE5gTnBOgE6QTqBOsE7ATtBO4E7wTwBPEE8gTzBPQE9QT2BPcE+AT5BPoE+wT8BP0E/gT/BQAFAQUCBQMFBAUFBQYFBwUIBQkFCgULBQwFDQUOBQ8FEAURBRIFEwUUBRUFFgUXBRgFGQUaBRsFHAUdBR4FHwUgBSEFIgUjBSQFJQUmBScFKAUpBSoFKwUsBS0FLgUvBTAFMQUyBTMFNAU1BTYFNwU4BTkFOgU7BTwFPQU+BT8FQAVBBUIFQwVEBUUFRgVHBUgFSQVKBUsFTAVNBU4FTwVQBVEFUgVTBVQFVQVWBVcFWAVZBVoFWwVcBV0FXgVfBWAFYQViBWMFZAVlBWYFZwVoBWkFagVrBWwFbQVuBW8FcAVxBXIFcwV0BXUFdgV3BXgFeQV6BXsFfAV9BX4FfwWABYEFggWDBYQFhQWGBYcFiAWJBYoFiwWMBY0FjgWPBZAFkQWSBZMFlAWVBZYFlwWYBZkFmgWbBZwFnQWeBZ8FoAWhBaIFowWkBaUFpgWnBagFqQWqBasFrAWtBa4FrwWwBbEFsgWzBbQFtQW2BbcFuAW5BboFuwW8Bb0FvgW/BcAFwQXCBcMFxAXFBcYFxwXIBckFygXLBcwFzQXOBc8F0AXRBdIF0wXUBdUF1gXXBdgF2QXaBdsF3AXdBd4F3wXgBeEF4gXjBeQF5QXmBecF6AXpBeoF6wXsBe0F7gXvBfAF8QXyBfMF9AX1BfYF9wX4BfkF+gX7BfwF/QX+Bf8GAAYBBgIGAwYEBgUGBgYHBggGCQYKBgsGDAYNBg4GDwYQBhEGEgYTBhQGFQYWBhcGGAYZBhoGGwYcBh0GHgYfBiAGIQYiBiMGJAYlBiYGJwYoBikGKgYrBiwGLQYuBi8GMAYxBjIGMwY0BjUGNgY3BjgGOQY6BjsGPAY9Bj4GPwZABkEGQgZDBkQGRQZGBkcGSAZJBkoGSwZMBk0GTgZPBlAGUQZSBlMGVAZVBlYGVwZYBlkGWgZbBlwGXQZeBl8GYAZhBmIGYwZkBmUGZgZnBmgGaQZqBmsGbAZtBm4GbwZwBnEGcgZzBnQGdQZ2BncGeAZ5BnoGewZ8Bn0GfgZ/BoAGgQaCBoMGhAaFBoYGhwaIBokGigaLBowGjQaOBo8GkAaRBpIGkwaUBpUGlgaXBpgGmQaaBpsGnAadBp4GnwagBqEGogajBqQGpQamBqcGqAapBqoGqwasBq0GrgavBrAGsQayBrMGtAa1BrYGtwa4BrkGuga7BrwGvQa+Br8GwAbBBsIGwwbEBsUGxgbHBsgGyQbKBssGzAbNBs4GzwbQBtEG0gbTBtQG1QbWBtcG2AbZBtoG2wbcBt0G3gbfBuAG4QbiBuMG5AblBuYG5wboBukG6gbrBuwG7QbuBu8G8AbxBvIG8wb0BvUG9gb3BvgG+Qb6BvsG/Ab9Bv4G/wcABwEHAgcDBwQHBQcGBwcHCAcJBwoHCwcMBw0HDgcPBxAHEQcSBxMHFAcVBxYHFwcYBxkHGgcbBxwHHQceBx8HIAchByIHIwckByUHJgcnBygHKQcqBysHLActBy4HLwcwBzEHMgczBzQHNQc2BzcHOAc5BzoHOwc8Bz0HPgc/B0AHQQdCB0MHRAdFB0YHRwdIB0kHSgdLB0wHTQdOB08HUAdRB1IHUwdUB1UHVgdXB1gHWQdaB1sHXAddB14HXwdgB2EHYgdjB2QHZQdmB2cHaAdpB2oHawdsB20HbgdvB3AHcQdyB3MHdAd1B3YHdwd4B3kHegd7B3wHfQd+B38HgAeBB4IHgweEB4UHhgeHB4gHiQeKB4sHjAeNB44HjweQB5EHkgeTB5QHlQeWB5cHmAeZB5oHmwecB50HngefB6AHoQeiB6MHpAelB6YHpweoB6kHqgerB6wHrQeuB68HsAexB7IHswe0B7UHtge3B7gHuQe6B7sHvAe9B74HvwfAB8EHwgfDB8QHxQfGB8cHyAfJB8oHywfMB80HzgfPB9AH0QfSB9MH1AfVB9YH1wfYB9kH2gfbB9wH3QfeB98H4AfhB+IH4wfkB+UH5gfnB+gH6QfqB+sH7AftB+4H7wfwB/EH8gfzB/QH9Qf2B/cH+Af5B/oH+wf8B/0H/gf/CAAIAQgCCAMIBAgFCAYIBwgICAkICggLCAwIDQgOCA8IEAgRCBIIEwgUCBUIFggXCBgIGQgaCBsIHAgdCB4IHwggCCEIIggjCCQIJQgmCCcIKAgpCCoIKwgsCC0ILggvCDAIMQgyCDMINAg1CDYINwg4CDkIOgg7CDwIPQg+CD8IQAhBCEIIQwhECEUIRghHCEgISQhKCEsg+wy3+iS3AfcQt/kstwP3EPoEFf58+YT6fAf9WP4nFfnSB/fF/DMFprAV+8X4NwX49gamYhX90gf7xfgzBXBmFffF/DcF/PYGDg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4OAAEBAQr4HwwmmhwZLRL7joscBUaLBr0KvQv65xUD6AB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAA=="); +} + +#font-validator { + padding: 0; + margin: 0; + font-size: 18px; + + position: absolute; + top: -100px; + left: -100px +} diff --git a/app/editor/base/font.js b/app/editor/base/font.js index 84ef628b..ba1dec1d 100644 --- a/app/editor/base/font.js +++ b/app/editor/base/font.js @@ -103,6 +103,20 @@ thin.Font.getFonts = function() { }; +/** + * @param {string} family + * @return {boolean} + */ +thin.Font.isRegistered = function (family) { + var detected = goog.array.find(thin.Font.fontRegistry_, + function (font) { + return font.getFamily() == family; + }); + + return detected !== null; +} + + /** * @type {Object.} * @private diff --git a/app/editor/base/platform/fontvalidator.js b/app/editor/base/platform/fontvalidator.js new file mode 100644 index 00000000..c3ef2d3a --- /dev/null +++ b/app/editor/base/platform/fontvalidator.js @@ -0,0 +1,68 @@ +// Copyright (C) 2011 Matsukei Co.,Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +goog.provide('thin.platform.FontValidator'); + +goog.require('goog.dom'); +goog.require('goog.style'); + + +/** + * @constructor + */ +thin.platform.FontValidator = function () { + /** + * @type {Element} + * @private + */ + this.element_ = goog.dom.getElement('font-validator'); +}; +goog.addSingletonGetter(thin.platform.FontValidator); + + +/** + * @param {string} family + * @return {boolean} + */ +thin.platform.FontValidator.validate = function (family) { + return thin.platform.FontValidator.getInstance().validate(family); +}; + + +/** + * @define {string} + */ +thin.platform.FontValidator.BLANK_FONT_FAMILY = 'AdobeBlank'; + + +/** + * @param {string} family + * @return {boolean} + */ +thin.platform.FontValidator.prototype.validate = function (family) { + this.setFontFamily_(family); + return goog.style.getSize(this.element_).width > 1; +}; + + +/** + * @param {string} family + * @return {void} + * @private + */ +thin.platform.FontValidator.prototype.setFontFamily_ = function (family) { + var style = family + ',' + thin.platform.FontValidator.BLANK_FONT_FAMILY; + goog.style.setStyle(this.element_, 'font-family', style); +}; diff --git a/app/editor/ui/fontselect.js b/app/editor/ui/fontselect.js index 11b8f9a5..0d0c3da5 100644 --- a/app/editor/ui/fontselect.js +++ b/app/editor/ui/fontselect.js @@ -19,6 +19,7 @@ goog.provide('thin.ui.FontOptionMenuRenderer'); goog.require('goog.array'); goog.require('goog.style'); goog.require('thin.Font'); +goog.require('thin.platform.FontValidator'); goog.require('thin.ui.ComboBox'); goog.require('thin.ui.ComboBoxItem'); @@ -26,6 +27,8 @@ goog.require('thin.ui.ComboBoxItem'); goog.require('thin.ui.OptionMenu'); goog.require('thin.ui.OptionMenuRenderer'); +goog.require('thin.ui.Input.Validator'); + /** * @param {Array.} fonts @@ -41,10 +44,32 @@ thin.ui.FontSelect = function(fonts, opt_menuRenderer) { this.addFonts(fonts); this.setValue(thin.Font.getDefaultFontFamily()); this.setTextAlignLeft(); + + this.initValidator_(); }; goog.inherits(thin.ui.FontSelect, thin.ui.ComboBox); +thin.ui.FontSelect.prototype.initValidator_ = function () { + var fontValidator = new thin.ui.Input.Validator(this); + + fontValidator.setAllowBlank(false); + fontValidator.setMethod(function (fontFamily) { + fontValidator.setMessage(thin.t('error_family_is_not_a_valid_font', {'family': fontFamily})); + + if (thin.Font.isRegistered(fontFamily)) { + return true; + } + if (thin.platform.FontValidator.validate(fontFamily)) { + return true; + } + + return false; + }); + + this.getInput().setValidator(fontValidator); +}; + /** @inheritDoc */ thin.ui.FontSelect.prototype.setValue = function(name) { goog.base(this, 'setValue', name || thin.Font.getDefaultFontFamily()); diff --git a/app/index.html b/app/index.html index 90408c9c..35d914e6 100644 --- a/app/index.html +++ b/app/index.html @@ -272,5 +272,7 @@

Aa diff --git a/app/locales/en.js b/app/locales/en.js index 048b9985..05cef85a 100644 --- a/app/locales/en.js +++ b/app/locales/en.js @@ -212,6 +212,7 @@ App.addLocale({ error_failed_to_load_image: 'Failed to load image.', error_no_valid_placeholder_included: 'No a valid placeholder included.', error_unexpected_error: 'An unexpected error occurred.', + error_family_is_not_a_valid_font: '{$family} is not a valid font.', notice_no_shapes: 'No shapes', warning_discard_changes: 'If you have unsaved files, the changes will be discarded. Please be sure to save.', diff --git a/app/locales/ja.js b/app/locales/ja.js index c96a33b7..d098c754 100644 --- a/app/locales/ja.js +++ b/app/locales/ja.js @@ -212,6 +212,8 @@ App.addLocale({ error_failed_to_load_image: '画像ファイルの読み込みに失敗しました。', error_no_valid_placeholder_included: '有効なプレースホルダが一つも含まれていません。', error_unexpected_error: '予期しないエラーが発生しました。', + error_family_is_not_a_valid_font: '{$family} は有効なフォントではありません。', + notice_no_shapes: 'オブジェクトはありません', warning_discard_changes: '保存していないレイアウトがある場合は必ず保存して下さい。', warning_discard_changes_en: 'If you have unsaved files, the changes will be discarded. Please be sure to save.', diff --git a/app/locales/pt-BR.js b/app/locales/pt-BR.js index 987644f2..9f83226b 100644 --- a/app/locales/pt-BR.js +++ b/app/locales/pt-BR.js @@ -212,6 +212,7 @@ App.addLocale({ error_failed_to_load_image: 'Falha ao carregar a imagem.', error_no_valid_placeholder_included: 'Sem um espaco reservado valido incluido.', error_unexpected_error: 'Ocorreu um erro inesperado.', + error_family_is_not_a_valid_font: '{$family} is not a valid font.', notice_no_shapes: 'Nao ha formas', warning_discard_changes: 'Se voce tiver arquivos que nao foram salvos, as alteracoes serao descartadas.\nPor favor, nao se esqueca de salvar.', From c10ba30313cec2f558394d06cc280712839aeeb0 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Sun, 25 Mar 2018 02:09:16 +0900 Subject: [PATCH 05/28] Make selectable the font once used --- app/editor/base/font.js | 46 +++++++++++++-- app/editor/ui/fontselect.js | 102 +++++++++++++++++++++++++++++++--- app/editor/ui/propertypane.js | 4 +- app/editor/ui/toolbar.js | 3 +- 4 files changed, 139 insertions(+), 16 deletions(-) diff --git a/app/editor/base/font.js b/app/editor/base/font.js index ba1dec1d..71303347 100644 --- a/app/editor/base/font.js +++ b/app/editor/base/font.js @@ -103,18 +103,48 @@ thin.Font.getFonts = function() { }; +/** + * @return {Array.} + */ +thin.Font.getBuiltinFonts = function () { + return goog.array.filter(thin.Font.fontRegistry_, + function (font) { + return font.isBuiltin(); + }); +}; + + +/** + * @return {Array.} + */ +thin.Font.getCustomFonts = function () { + return goog.array.filter(thin.Font.fontRegistry_, + function (font) { + return font.isCustom(); + }); +}; + + /** * @param {string} family * @return {boolean} */ thin.Font.isRegistered = function (family) { - var detected = goog.array.find(thin.Font.fontRegistry_, + var detected = thin.Font.findFontByFamily(family); + return detected !== null; +}; + + +/** + * @param {string} family + * @return {thin.Font?} + */ +thin.Font.findFontByFamily = function (family) { + return goog.array.find(thin.Font.fontRegistry_, function (font) { return font.getFamily() == family; }); - - return detected !== null; -} +}; /** @@ -192,3 +222,11 @@ thin.Font.prototype.getName = function() { thin.Font.prototype.isBuiltin = function() { return this.builtin_; }; + + +/** + * @return {boolean} + */ +thin.Font.prototype.isCustom = function () { + return !this.isBuiltin(); +}; diff --git a/app/editor/ui/fontselect.js b/app/editor/ui/fontselect.js index 0d0c3da5..c6a9b619 100644 --- a/app/editor/ui/fontselect.js +++ b/app/editor/ui/fontselect.js @@ -26,6 +26,7 @@ goog.require('thin.ui.ComboBoxItem'); goog.require('thin.ui.OptionMenu'); goog.require('thin.ui.OptionMenuRenderer'); +goog.require('thin.ui.MenuSeparator'); goog.require('thin.ui.Input.Validator'); @@ -41,7 +42,7 @@ thin.ui.FontSelect = function(fonts, opt_menuRenderer) { opt_menuRenderer || thin.ui.FontOptionMenuRenderer.getInstance()); goog.base(this, menu); - this.addFonts(fonts); + this.loadFonts_(); this.setValue(thin.Font.getDefaultFontFamily()); this.setTextAlignLeft(); @@ -50,6 +51,37 @@ thin.ui.FontSelect = function(fonts, opt_menuRenderer) { goog.inherits(thin.ui.FontSelect, thin.ui.ComboBox); +/** + * @type {Array.} + * @private + */ +thin.ui.FontSelect.activeControlRegistry_ = []; + + +/** + * @param {thin.ui.FontSelect} control + */ +thin.ui.FontSelect.registerControl = function (control) { + goog.array.insert(thin.ui.FontSelect.activeControlRegistry_, control); +}; + + +/** + * @param {thin.ui.FontSelect} control + */ +thin.ui.FontSelect.unregisterControl = function (control) { + goog.array.remove(thin.ui.FontSelect.activeControlRegistry_, control); +}; + + +thin.ui.FontSelect.reloadFontsOfAllControls = function () { + goog.array.forEach(thin.ui.FontSelect.activeControlRegistry_, + function (control) { + control.reloadFonts(); + }); +}; + + thin.ui.FontSelect.prototype.initValidator_ = function () { var fontValidator = new thin.ui.Input.Validator(this); @@ -70,32 +102,88 @@ thin.ui.FontSelect.prototype.initValidator_ = function () { this.getInput().setValidator(fontValidator); }; + /** @inheritDoc */ thin.ui.FontSelect.prototype.setValue = function(name) { goog.base(this, 'setValue', name || thin.Font.getDefaultFontFamily()); }; +thin.ui.FontSelect.prototype.reloadFonts = function () { + this.getMenu().removeChildren(true); + this.loadFonts_(); +}; + + /** - * @param {Array.} fonts + * @param {string} family + * @private + */ +thin.ui.FontSelect.prototype.registerCustomFont_ = function (family) { + if (!thin.Font.isRegistered(family)) { + thin.Font.register(family); + + thin.ui.FontSelect.reloadFontsOfAllControls(); + } +}; + + +/** + * @private */ -thin.ui.FontSelect.prototype.addFonts = function(fonts) { - goog.array.forEach(fonts, function(font) { - this.addFont(font); - }, this); +thin.ui.FontSelect.prototype.loadFonts_ = function () { + goog.array.forEach(thin.Font.getBuiltinFonts(), + function(font) { + this.addFont_(font); + }, this); + + var customFonts = thin.Font.getCustomFonts(); + + if (!goog.array.isEmpty(customFonts)) { + this.addItem(new thin.ui.MenuSeparator()); + + goog.array.forEach(customFonts, + function (font) { + this.addFont_(font); + }, this); + } }; /** * @param {thin.Font} font + * @private */ -thin.ui.FontSelect.prototype.addFont = function(font) { +thin.ui.FontSelect.prototype.addFont_ = function(font) { var item = new thin.ui.ComboBoxItem(font.getFamily()); item.setSticky(true); this.addItem(item); }; +/** @override */ +thin.ui.FontSelect.prototype.enterDocument = function () { + goog.base(this, 'enterDocument'); + + thin.ui.FontSelect.registerControl(this); + + var handler = this.getHandler(); + + handler.listen(this.getInput(), goog.ui.Component.EventType.CHANGE, + function (e) { + this.registerCustomFont_(this.getValue()); + }, false, this); +}; + + +/** @override */ +thin.ui.FontSelect.prototype.exitDocument = function () { + goog.base(this, 'exitDocument'); + + thin.ui.FontSelect.unregisterControl(this); +}; + + /** * @constructor * @extends {thin.ui.OptionMenuRenderer} diff --git a/app/editor/ui/propertypane.js b/app/editor/ui/propertypane.js index a9c0901b..0e0825a9 100644 --- a/app/editor/ui/propertypane.js +++ b/app/editor/ui/propertypane.js @@ -40,7 +40,6 @@ goog.require('goog.ui.Component.State'); goog.require('goog.ui.Component.EventType'); goog.require('goog.ui.Checkbox'); goog.require('goog.ui.Checkbox.State'); -goog.require('thin.Font'); goog.require('thin.ui.Component'); goog.require('thin.ui.Select'); goog.require('thin.ui.ComboBox'); @@ -1524,8 +1523,7 @@ thin.ui.PropertyPane.FontSelectProperty = function(opt_label) { var menuRenderer = goog.ui.ContainerRenderer.getCustomRenderer( thin.ui.FontOptionMenuRenderer, thin.ui.getCssName(propCssClass, 'font-selectmenu')); - var control = new thin.ui.FontSelect(thin.Font.getFonts(), - /** @type {thin.ui.FontOptionMenuRenderer} */ (menuRenderer)); + var control = new thin.ui.FontSelect(/** @type {thin.ui.FontOptionMenuRenderer} */ (menuRenderer)); control.getMenu().setMaxHeight(250); diff --git a/app/editor/ui/toolbar.js b/app/editor/ui/toolbar.js index d2b17047..7219b58e 100644 --- a/app/editor/ui/toolbar.js +++ b/app/editor/ui/toolbar.js @@ -30,7 +30,6 @@ goog.require('goog.array'); goog.require('goog.ui.Component.EventType'); goog.require('goog.ui.Separator'); goog.require('goog.ui.ControlRenderer'); -goog.require('thin.Font'); goog.require('thin.ui.Component'); goog.require('thin.ui.Button'); goog.require('thin.ui.ButtonRenderer'); @@ -249,7 +248,7 @@ goog.inherits(thin.ui.ToolbarSelect, thin.ui.Select); * @extends {thin.ui.FontSelect} */ thin.ui.ToolbarFontSelect = function() { - thin.ui.FontSelect.call(this, thin.Font.getFonts()); + thin.ui.FontSelect.call(this); // this.addClassName(thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'select')); }; goog.inherits(thin.ui.ToolbarFontSelect, thin.ui.FontSelect); From 7c7b48c3c98c1203623384929f637d6cedeff986 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Thu, 5 Apr 2018 02:34:09 +0900 Subject: [PATCH 06/28] Fixed undo/redo does not work when cusor is in a text-field --- app/editor/core/workspace/workspace.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/editor/core/workspace/workspace.js b/app/editor/core/workspace/workspace.js index 4ac676f3..6f122567 100644 --- a/app/editor/core/workspace/workspace.js +++ b/app/editor/core/workspace/workspace.js @@ -260,10 +260,12 @@ thin.core.Workspace.prototype.handleUndoRedoKeyEvent_ = function(e) { case keyCodes.Z: this.undo(); this.enablingOnceKeyEventHandling_(true); + e.preventDefault(); break; case keyCodes.Y: this.redo(); this.enablingOnceKeyEventHandling_(true); + e.preventDefault(); break; } } From eb8ed516eaa736bbda82561585a62b69bc07c639 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Fri, 4 May 2018 14:15:45 +0900 Subject: [PATCH 07/28] Save custom-fonts in *.tlf --- app/editor/core/layout.js | 14 +++ app/editor/core/layout/allusedfontfamilies.js | 113 ++++++++++++++++++ app/editor/core/workspace/workspace.js | 7 ++ app/editor/layout/format.js | 19 ++- 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 app/editor/core/layout/allusedfontfamilies.js diff --git a/app/editor/core/layout.js b/app/editor/core/layout.js index 14f5f68d..01119b58 100644 --- a/app/editor/core/layout.js +++ b/app/editor/core/layout.js @@ -39,6 +39,7 @@ goog.require('thin.core.StateManager'); goog.require('thin.core.ShapeIdManager'); goog.require('thin.core.ShapeIdManager.DefaultPrefix'); goog.require('thin.core.ClipboardShapeManager'); +goog.require('thin.core.layout.AllUsedFontFamilies'); /** @@ -378,6 +379,19 @@ thin.core.Layout.prototype.createHelpersElement = function(tagName, attrs) { }; +/** + * @return {Array.} + */ +thin.core.Layout.prototype.getUsedCustomFonts = function () { + var customFonts = thin.Font.getCustomFonts(); + var allUsedFontFamilies = thin.core.layout.AllUsedFontFamilies.get(this); + + return goog.array.filter(customFonts, function (font) { + return goog.array.contains(allUsedFontFamilies, font.getFamily()); + }); +}; + + /** * @return {Object} */ diff --git a/app/editor/core/layout/allusedfontfamilies.js b/app/editor/core/layout/allusedfontfamilies.js new file mode 100644 index 00000000..408fe9fd --- /dev/null +++ b/app/editor/core/layout/allusedfontfamilies.js @@ -0,0 +1,113 @@ +// Copyright (C) 2011 Matsukei Co.,Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +goog.provide('thin.core.layout.AllUsedFontFamilies'); + +goog.require('goog.array'); +goog.require('goog.Disposable'); +goog.require('thin.core.ListShape'); +goog.require('thin.core.AbstractTextGroup'); + + +/** + * @param {thin.core.Layout} layout + * @constructor + * @extends {goog.Disposable} + */ +thin.core.layout.AllUsedFontFamilies = function (layout) { + /** + * @type {thin.core.layout} + * @private + */ + this.layout_ = layout; +}; +goog.inherits(thin.core.layout.AllUsedFontFamilies, goog.Disposable); + + +/** + * @param {thin.core.layout} layout + * @return {Array.} + */ +thin.core.layout.AllUsedFontFamilies.get = function (layout) { + var action = new thin.core.layout.AllUsedFontFamilies(layout); + return action.get(); +}; + + +/** + * @return {Array.} + */ +thin.core.layout.AllUsedFontFamilies.prototype.get = function () { + var shapesInLayout = this.layout_.getManager().getShapesManager().get(); + return this.get_(shapesInLayout); +}; + + +/** + * @param {Array} shapes Array. + * @private + */ +thin.core.layout.AllUsedFontFamilies.prototype.get_ = function (shapes) { + var targetShapes = this.filterTarget_(shapes); + + var families = goog.array.map(targetShapes, + function (shape) { + if (shape instanceof thin.core.ListShape) { + return /** @type {Array.} */(this.getInListShape_(shape)); + } else if (shape instanceof thin.core.AbstractTextGroup) { + return /** @type {string} */(shape.getFontFamily()); + } + }, this); + + return goog.array.flatten(families); +}; + + +/** + * @param {thin.core.ListShape} shape + * @return {Array.} + */ +thin.core.layout.AllUsedFontFamilies.prototype.getInListShape_ = function (shape) { + var families = []; + + shape.forEachSectionShape(function (section) { + this.get_(section.getManager().getShapesManager().get()); + }, this) + + return families; +}; + + +/* + * @param {Array} shapes Array. + * @return {Array} Filtered shapes + * @private + */ +thin.core.layout.AllUsedFontFamilies.prototype.filterTarget_ = function (shapes) { + return goog.array.filter(shapes, function (shape) { + return shape instanceof thin.core.ListShape || shape instanceof thin.core.AbstractTextGroup; + }); +}; + + +/** + * @override + */ +thin.core.layout.AllUsedFontFamilies.prototype.disposeInternal = function () { + goog.base(this, 'disposeInternal'); + + this.layout_ = null; + delete this.layout_; +}; diff --git a/app/editor/core/workspace/workspace.js b/app/editor/core/workspace/workspace.js index 6f122567..9c189d02 100644 --- a/app/editor/core/workspace/workspace.js +++ b/app/editor/core/workspace/workspace.js @@ -613,9 +613,16 @@ thin.core.Workspace.prototype.setFormat = function(format) { thin.core.Workspace.prototype.getSaveFormat_ = function() { var layout = this.layout_; var format = this.format; + format.setItems(layout.asJSON()); format.setLayoutGuides(layout.getHelpers().getLayoutGuideHelper().getGuides()); + format.setCustomFonts( + goog.array.map(layout.getUsedCustomFonts(), function (font) { + return font.getFamily(); + }) + ); + return format.toJSON(); }; diff --git a/app/editor/layout/format.js b/app/editor/layout/format.js index 8f78ee7a..3b85532c 100644 --- a/app/editor/layout/format.js +++ b/app/editor/layout/format.js @@ -111,7 +111,8 @@ thin.layout.Format.prototype.toJSON = function() { "version": this.version_, "items": this.items_, "state": { - "layout-guides": this.getLayoutGuides() + "layout-guides": this.getLayoutGuides(), + "custom-fonts": this.getCustomFonts() } }; goog.object.extend(object, this.page.asJSON()); @@ -136,6 +137,14 @@ thin.layout.Format.prototype.getLayoutGuides = function() { }; +/** + * @return {Array} + */ +thin.layout.Format.prototype.getCustomFonts = function () { + return this.state_['custom-fonts'] || []; +}; + + /** * @param {string} version */ @@ -160,6 +169,14 @@ thin.layout.Format.prototype.setLayoutGuides = function(guides) { }; +/** + * @param {Array.} fonts + */ +thin.layout.Format.prototype.setCustomFonts = function (fonts) { + this.state_['custom-fonts'] = fonts; +}; + + /** * @param {Object} items */ From eaaa04d328d3c12deafbb5e8d66ea169a1004dab Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Fri, 4 May 2018 19:20:12 +0900 Subject: [PATCH 08/28] custom-fonts is sorted by acending --- app/editor/core/layout.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/editor/core/layout.js b/app/editor/core/layout.js index 01119b58..0619f83a 100644 --- a/app/editor/core/layout.js +++ b/app/editor/core/layout.js @@ -386,9 +386,13 @@ thin.core.Layout.prototype.getUsedCustomFonts = function () { var customFonts = thin.Font.getCustomFonts(); var allUsedFontFamilies = thin.core.layout.AllUsedFontFamilies.get(this); - return goog.array.filter(customFonts, function (font) { + var usedCustomFonts = goog.array.filter(customFonts, function (font) { return goog.array.contains(allUsedFontFamilies, font.getFamily()); }); + + goog.array.sort(usedCustomFonts); + + return usedCustomFonts; }; From 38fdc978fb82d1aeada3ecc0ed51390143802fab Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Fri, 4 May 2018 19:23:09 +0900 Subject: [PATCH 09/28] Fixed AllUsedFontFamilies does not include font in List --- app/editor/core/layout/allusedfontfamilies.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/editor/core/layout/allusedfontfamilies.js b/app/editor/core/layout/allusedfontfamilies.js index 408fe9fd..0c8e2024 100644 --- a/app/editor/core/layout/allusedfontfamilies.js +++ b/app/editor/core/layout/allusedfontfamilies.js @@ -80,13 +80,13 @@ thin.core.layout.AllUsedFontFamilies.prototype.get_ = function (shapes) { * @return {Array.} */ thin.core.layout.AllUsedFontFamilies.prototype.getInListShape_ = function (shape) { - var families = []; + var familiesEachSection = []; shape.forEachSectionShape(function (section) { - this.get_(section.getManager().getShapesManager().get()); + familiesEachSection.push(this.get_(section.getManager().getShapesManager().get())); }, this) - return families; + return goog.array.flatten(familiesEachSection); }; From c2bc6e49301bcf7a2a5486e428fc2af9cacbcfef Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Sun, 6 May 2018 01:27:00 +0900 Subject: [PATCH 10/28] Fix comment format --- app/editor/core/layout/allusedfontfamilies.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/editor/core/layout/allusedfontfamilies.js b/app/editor/core/layout/allusedfontfamilies.js index 0c8e2024..51617416 100644 --- a/app/editor/core/layout/allusedfontfamilies.js +++ b/app/editor/core/layout/allusedfontfamilies.js @@ -90,7 +90,7 @@ thin.core.layout.AllUsedFontFamilies.prototype.getInListShape_ = function (shape }; -/* +/** * @param {Array} shapes Array. * @return {Array} Filtered shapes * @private From 456dcaf66c01ee248bc59611a01ea5db71e65b76 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Sun, 6 May 2018 04:31:28 +0900 Subject: [PATCH 11/28] Restore custom-fonts from .tlf --- app/editor/core/layout.js | 2 +- .../core/workspace/customfontregistry.js | 75 +++++++++++++++++++ app/editor/core/workspace/workspace.js | 6 ++ app/editor/layout/format.js | 15 +++- app/editor/ui/fontselect.js | 74 +++++++----------- 5 files changed, 120 insertions(+), 52 deletions(-) create mode 100644 app/editor/core/workspace/customfontregistry.js diff --git a/app/editor/core/layout.js b/app/editor/core/layout.js index 0619f83a..dd80dcdb 100644 --- a/app/editor/core/layout.js +++ b/app/editor/core/layout.js @@ -383,7 +383,7 @@ thin.core.Layout.prototype.createHelpersElement = function(tagName, attrs) { * @return {Array.} */ thin.core.Layout.prototype.getUsedCustomFonts = function () { - var customFonts = thin.Font.getCustomFonts(); + var customFonts = this.getWorkspace().customFonts.get(); var allUsedFontFamilies = thin.core.layout.AllUsedFontFamilies.get(this); var usedCustomFonts = goog.array.filter(customFonts, function (font) { diff --git a/app/editor/core/workspace/customfontregistry.js b/app/editor/core/workspace/customfontregistry.js new file mode 100644 index 00000000..2d29fa22 --- /dev/null +++ b/app/editor/core/workspace/customfontregistry.js @@ -0,0 +1,75 @@ +// Copyright (C) 2011 Matsukei Co.,Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +goog.provide('thin.core.workspace.CustomFontRegistry'); + +goog.require('goog.Disposable'); +goog.require('thin.Font'); + + +/** + * @param {Array.=} opt_families + * @extends {goog.Disposable} + * @constructor + */ +thin.core.workspace.CustomFontRegistry = function (opt_families) { + goog.base(this); + + /** + * @type {Array.} + * @private + */ + this.fonts_ = goog.array.map(opt_families || [], + function (family) { + return new thin.Font(family); + }); +}; +goog.inherits(thin.core.workspace.CustomFontRegistry, goog.Disposable); + + +/** + * @param {string} fontFamily + */ +thin.core.workspace.CustomFontRegistry.prototype.register = function (fontFamily) { + this.fonts_.push(new thin.Font(fontFamily)); +}; + + +/** + * @return {Array.} + */ +thin.core.workspace.CustomFontRegistry.prototype.get = function () { + return this.fonts_; +}; + + +/** + * @param {string} fontFamily + * @return {boolean} + */ +thin.core.workspace.CustomFontRegistry.prototype.contains = function (fontFamily) { + var families = goog.array.map(this.fonts_, function (font) { font.getFamily() }); + return goog.array.contains(families, fontFamily); +}; + + +/** + * @override + */ +thin.core.workspace.CustomFontRegistry.prototype.disposeInternal = function () { + goog.base(this, 'disposeInternal'); + + this.fonts_ = null; +}; diff --git a/app/editor/core/workspace/workspace.js b/app/editor/core/workspace/workspace.js index 9c189d02..da71e29c 100644 --- a/app/editor/core/workspace/workspace.js +++ b/app/editor/core/workspace/workspace.js @@ -37,6 +37,7 @@ goog.require('thin.layout.FormatPage.PaperName'); goog.require('thin.layout.FormatPage.DirectionType'); goog.require('thin.layout.document'); goog.require('thin.Font'); +goog.require('thin.core.workspace.CustomFontRegistry'); /** @@ -59,6 +60,11 @@ thin.core.Workspace = function(format, opt_file) { this.setFile(new thin.layout.File()); } + /** + * @type {thin.core.workspace.CustomFontRegistry} + */ + this.customFonts = new thin.core.workspace.CustomFontRegistry(format.getCustomFonts()); + /** * @type {string} * @private diff --git a/app/editor/layout/format.js b/app/editor/layout/format.js index 3b85532c..78a7c851 100644 --- a/app/editor/layout/format.js +++ b/app/editor/layout/format.js @@ -45,8 +45,9 @@ thin.layout.Format = function(opt_format) { this.isOverWritableVersion_ = thin.Compatibility.check(currentVersion, '>', formatVersion); this.version_ = formatVersion; - if (state && (guides = state['layout-guides'])) { - this.setLayoutGuides(guides); + if (state) { + this.setLayoutGuides(state['layout-guides'] || []); + this.setCustomFonts(state['custom-fonts'] || []); } } else { this.version_ = currentVersion; @@ -137,6 +138,14 @@ thin.layout.Format.prototype.getLayoutGuides = function() { }; +/** + * @return {Array.} + */ +thin.layout.Format.prototype.getCustomFonts = function () { + return this.state_['custom-fonts'] || []; +}; + + /** * @return {Array} */ @@ -170,7 +179,7 @@ thin.layout.Format.prototype.setLayoutGuides = function(guides) { /** - * @param {Array.} fonts + * @param {Array.} fonts */ thin.layout.Format.prototype.setCustomFonts = function (fonts) { this.state_['custom-fonts'] = fonts; diff --git a/app/editor/ui/fontselect.js b/app/editor/ui/fontselect.js index c6a9b619..f2d523f3 100644 --- a/app/editor/ui/fontselect.js +++ b/app/editor/ui/fontselect.js @@ -51,37 +51,6 @@ thin.ui.FontSelect = function(fonts, opt_menuRenderer) { goog.inherits(thin.ui.FontSelect, thin.ui.ComboBox); -/** - * @type {Array.} - * @private - */ -thin.ui.FontSelect.activeControlRegistry_ = []; - - -/** - * @param {thin.ui.FontSelect} control - */ -thin.ui.FontSelect.registerControl = function (control) { - goog.array.insert(thin.ui.FontSelect.activeControlRegistry_, control); -}; - - -/** - * @param {thin.ui.FontSelect} control - */ -thin.ui.FontSelect.unregisterControl = function (control) { - goog.array.remove(thin.ui.FontSelect.activeControlRegistry_, control); -}; - - -thin.ui.FontSelect.reloadFontsOfAllControls = function () { - goog.array.forEach(thin.ui.FontSelect.activeControlRegistry_, - function (control) { - control.reloadFonts(); - }); -}; - - thin.ui.FontSelect.prototype.initValidator_ = function () { var fontValidator = new thin.ui.Input.Validator(this); @@ -89,7 +58,9 @@ thin.ui.FontSelect.prototype.initValidator_ = function () { fontValidator.setMethod(function (fontFamily) { fontValidator.setMessage(thin.t('error_family_is_not_a_valid_font', {'family': fontFamily})); - if (thin.Font.isRegistered(fontFamily)) { + var workspace = thin.core.getActiveWorkspace(); + + if (workspace.customFonts.contains(fontFamily)) { return true; } if (thin.platform.FontValidator.validate(fontFamily)) { @@ -120,10 +91,10 @@ thin.ui.FontSelect.prototype.reloadFonts = function () { * @private */ thin.ui.FontSelect.prototype.registerCustomFont_ = function (family) { - if (!thin.Font.isRegistered(family)) { - thin.Font.register(family); + var customFontRegistry = thin.core.getActiveWorkspace().customFonts; - thin.ui.FontSelect.reloadFontsOfAllControls(); + if (!customFontRegistry.contains(family)) { + customFontRegistry.register(family); } }; @@ -132,20 +103,26 @@ thin.ui.FontSelect.prototype.registerCustomFont_ = function (family) { * @private */ thin.ui.FontSelect.prototype.loadFonts_ = function () { + var workspace, customFonts; + goog.array.forEach(thin.Font.getBuiltinFonts(), function(font) { this.addFont_(font); }, this); - var customFonts = thin.Font.getCustomFonts(); + workspace = thin.core.getActiveWorkspace(); - if (!goog.array.isEmpty(customFonts)) { - this.addItem(new thin.ui.MenuSeparator()); + if (workspace) { + customFonts = workspace.customFonts.get(); - goog.array.forEach(customFonts, - function (font) { - this.addFont_(font); - }, this); + if (!goog.array.isEmpty(customFonts)) { + this.addItem(new thin.ui.MenuSeparator()); + + goog.array.forEach(customFonts, + function (font) { + this.addFont_(font); + }, this); + } } }; @@ -165,8 +142,6 @@ thin.ui.FontSelect.prototype.addFont_ = function(font) { thin.ui.FontSelect.prototype.enterDocument = function () { goog.base(this, 'enterDocument'); - thin.ui.FontSelect.registerControl(this); - var handler = this.getHandler(); handler.listen(this.getInput(), goog.ui.Component.EventType.CHANGE, @@ -176,11 +151,14 @@ thin.ui.FontSelect.prototype.enterDocument = function () { }; -/** @override */ -thin.ui.FontSelect.prototype.exitDocument = function () { - goog.base(this, 'exitDocument'); +/** + * @override + */ +thin.ui.FontSelect.prototype.showMenu_ = function () { + // Reload fonts before menu shown + this.reloadFonts(); - thin.ui.FontSelect.unregisterControl(this); + goog.base(this, 'showMenu_'); }; From e5a055a73699a6df2abd5e556e3004504892adf4 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Sun, 6 May 2018 04:31:59 +0900 Subject: [PATCH 12/28] Remove unnecessary code --- app/editor/base/font.js | 72 ++++++++--------------------------------- 1 file changed, 13 insertions(+), 59 deletions(-) diff --git a/app/editor/base/font.js b/app/editor/base/font.js index 71303347..e2e92fe3 100644 --- a/app/editor/base/font.js +++ b/app/editor/base/font.js @@ -22,10 +22,9 @@ goog.require('thin.platform.Font'); /** * @param {string} family * @param {string=} opt_name - * @param {boolean=} opt_builtin * @constructor */ -thin.Font = function(family, opt_name, opt_builtin) { +thin.Font = function(family, opt_name) { /** * @type {string} * @private @@ -37,12 +36,6 @@ thin.Font = function(family, opt_name, opt_builtin) { * @private */ this.name_ = opt_name || family; - - /** - * @type {boolean} - * @private - */ - this.builtin_ = opt_builtin || false; }; @@ -50,7 +43,7 @@ thin.Font = function(family, opt_name, opt_builtin) { * @type {Array.} * @private */ -thin.Font.fontRegistry_ = []; +thin.Font.builtinFontRegistry_ = []; /** @@ -63,12 +56,11 @@ thin.Font.defaultFont_; /** * @param {string} family * @param {string=} opt_name - * @param {boolean=} opt_builtin * @return {thin.Font} */ -thin.Font.register = function(family, opt_name, opt_builtin) { - var font = new thin.Font(family, opt_name || family, opt_builtin); - thin.Font.fontRegistry_.push(font); +thin.Font.register = function(family, opt_name) { + var font = new thin.Font(family, opt_name || family); + thin.Font.builtinFontRegistry_.push(font); return font; }; @@ -78,12 +70,12 @@ thin.Font.init = function() { font.defaultFont_ = font.register('Helvetica', null, true); - font.register('Courier New', null, true); - font.register('Times New Roman', null, true); - font.register('IPAMincho', 'IPA ' + thin.t('font_mincho'), true); - font.register('IPAPMincho', 'IPA P' + thin.t('font_mincho'), true); - font.register('IPAGothic', 'IPA ' + thin.t('font_gothic'), true); - font.register('IPAPGothic', 'IPA P' + thin.t('font_gothic'), true); + font.register('Courier New'); + font.register('Times New Roman'); + font.register('IPAMincho', 'IPA ' + thin.t('font_mincho')); + font.register('IPAPMincho', 'IPA P' + thin.t('font_mincho')); + font.register('IPAGothic', 'IPA ' + thin.t('font_gothic')); + font.register('IPAPGothic', 'IPA P' + thin.t('font_gothic')); }; @@ -98,30 +90,8 @@ thin.Font.getDefaultFontFamily = function() { /** * @return {Array.} */ -thin.Font.getFonts = function() { - return thin.Font.fontRegistry_; -}; - - -/** - * @return {Array.} - */ -thin.Font.getBuiltinFonts = function () { - return goog.array.filter(thin.Font.fontRegistry_, - function (font) { - return font.isBuiltin(); - }); -}; - - -/** - * @return {Array.} - */ -thin.Font.getCustomFonts = function () { - return goog.array.filter(thin.Font.fontRegistry_, - function (font) { - return font.isCustom(); - }); +thin.Font.getBuiltinFonts = function() { + return thin.Font.builtinFontRegistry_; }; @@ -214,19 +184,3 @@ thin.Font.prototype.getFamily = function() { thin.Font.prototype.getName = function() { return this.name_; }; - - -/** - * @return {boolean} - */ -thin.Font.prototype.isBuiltin = function() { - return this.builtin_; -}; - - -/** - * @return {boolean} - */ -thin.Font.prototype.isCustom = function () { - return !this.isBuiltin(); -}; From 43c39cc2c26e04353b5fde366282a3e5f840446d Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Sun, 6 May 2018 17:27:25 +0900 Subject: [PATCH 13/28] Fixed Combobox value breaks when undoing/redoing --- app/editor/boot.js | 5 +-- app/editor/core/workspace/workspace.js | 9 ++++- app/editor/ui/combobox.js | 2 +- app/editor/ui/toolbar.js | 18 +++++++++- app/editor/ui/toolbar/combobox.js | 47 ++++++++++++++++++++++++++ 5 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 app/editor/ui/toolbar/combobox.js diff --git a/app/editor/boot.js b/app/editor/boot.js index f20ed886..2185590a 100644 --- a/app/editor/boot.js +++ b/app/editor/boot.js @@ -47,6 +47,7 @@ goog.require('thin.ui.ToolbarSplitToggleButton'); goog.require('thin.ui.ToolbarToggleIconButton'); goog.require('thin.ui.ToolbarSelect'); goog.require('thin.ui.ToolbarFontSelect'); +goog.require('thin.ui.toolbar.ComboBox'); goog.require('thin.ui.ToggleGroup'); goog.require('thin.ui.MenuItem'); goog.require('thin.ui.MenuLinkItem'); @@ -819,7 +820,7 @@ thin.init_ = function() { }); // Zoom rate var toolZoomRate = toolbar.setupChild('zoom-rate', - new thin.ui.ComboBox(), dom.getElement('tbar-zoom-rate'), + new thin.ui.toolbar.ComboBox(), dom.getElement('tbar-zoom-rate'), function(combobox) { var zoomRateList = ['25', '50', '75', '100', '150', '200', '400', '600']; var comboboxItem; @@ -922,7 +923,7 @@ thin.init_ = function() { // Font size var toolSize = toolbar.setupChild('font-size', - new thin.ui.ComboBox(), dom.getElement('tbar-font-size'), + new thin.ui.toolbar.ComboBox(), dom.getElement('tbar-font-size'), function(combobox) { var comboboxItem; goog.array.forEach(thin.core.FontStyle.FONTSIZE_LIST, function(fontSize) { diff --git a/app/editor/core/workspace/workspace.js b/app/editor/core/workspace/workspace.js index da71e29c..1d9f8f28 100644 --- a/app/editor/core/workspace/workspace.js +++ b/app/editor/core/workspace/workspace.js @@ -1059,13 +1059,20 @@ thin.core.Workspace.prototype.focusElement = function(e) { var scrollTarget = this.getParent().getParent().getContentElement(); var captureLeft = scrollTarget.scrollLeft; - this.element_.focus(); + this.focus(); + var currentLeft = scrollTarget.scrollLeft; if(captureLeft != currentLeft){ scrollTarget.scrollLeft = captureLeft; } }; + +thin.core.Workspace.prototype.focus = function () { + this.element_.focus(); +}; + + /** @inheritDoc */ thin.core.Workspace.prototype.disposeInternal = function() { this.format.dispose(); diff --git a/app/editor/ui/combobox.js b/app/editor/ui/combobox.js index d703bc77..8a61e10f 100644 --- a/app/editor/ui/combobox.js +++ b/app/editor/ui/combobox.js @@ -328,4 +328,4 @@ thin.ui.ComboBoxItem.prototype.setSticky = function(sticky) { */ thin.ui.ComboBoxItem.prototype.isSticky = function() { return this.isSticky_; -}; \ No newline at end of file +}; diff --git a/app/editor/ui/toolbar.js b/app/editor/ui/toolbar.js index 7219b58e..a9c5fc3e 100644 --- a/app/editor/ui/toolbar.js +++ b/app/editor/ui/toolbar.js @@ -249,11 +249,27 @@ goog.inherits(thin.ui.ToolbarSelect, thin.ui.Select); */ thin.ui.ToolbarFontSelect = function() { thin.ui.FontSelect.call(this); - // this.addClassName(thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'select')); }; goog.inherits(thin.ui.ToolbarFontSelect, thin.ui.FontSelect); +/** @override */ +thin.ui.ToolbarFontSelect.prototype.enterDocument = function () { + goog.base(this, 'enterDocument'); + + var handler = this.getHandler(); + + handler.listen(this.getInput(), + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + function (e) { + var workspace = thin.core.getActiveWorkspace(); + if (workspace) { + workspace.focus(); + } + }, false, this); +}; + + /** * @param {goog.ui.MenuSeparatorRenderer=} opt_renderer * @constructor diff --git a/app/editor/ui/toolbar/combobox.js b/app/editor/ui/toolbar/combobox.js new file mode 100644 index 00000000..c65cfead --- /dev/null +++ b/app/editor/ui/toolbar/combobox.js @@ -0,0 +1,47 @@ +// Copyright (C) 2011 Matsukei Co.,Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +goog.provide('thin.ui.toolbar.ComboBox'); + +goog.require('thin.core'); +goog.require('thin.ui.ComboBox'); +goog.require('thin.ui.Input.EventType'); + +/** + * @param {thin.ui.OptionMenu=} opt_menu + * @constructor + * @extends {thin.ui.ComboBox} + */ +thin.ui.toolbar.ComboBox = function (opt_menu) { + goog.base(this, opt_menu); +}; +goog.inherits(thin.ui.toolbar.ComboBox, thin.ui.ComboBox); + + +/** @override */ +thin.ui.toolbar.ComboBox.prototype.enterDocument = function () { + goog.base(this, 'enterDocument'); + + var handler = this.getHandler(); + + handler.listen(this.getInput(), + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + function (e) { + var workspace = thin.core.getActiveWorkspace(); + if (workspace) { + workspace.focus(); + } + }, false, this); +}; From 8dcd16e65078209054b38a93eafe67853947b6c4 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Sun, 6 May 2018 17:56:09 +0900 Subject: [PATCH 14/28] make disposable --- app/editor/base/font.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/editor/base/font.js b/app/editor/base/font.js index e2e92fe3..368112cb 100644 --- a/app/editor/base/font.js +++ b/app/editor/base/font.js @@ -16,6 +16,7 @@ goog.provide('thin.Font'); goog.require('goog.array'); +goog.requrie('goog.Disposable'); goog.require('thin.platform.Font'); @@ -23,6 +24,7 @@ goog.require('thin.platform.Font'); * @param {string} family * @param {string=} opt_name * @constructor + * @extends {goog.Disposable} */ thin.Font = function(family, opt_name) { /** @@ -37,6 +39,7 @@ thin.Font = function(family, opt_name) { */ this.name_ = opt_name || family; }; +goog.inherits(thin.Font, goog.Disposable); /** @@ -184,3 +187,11 @@ thin.Font.prototype.getFamily = function() { thin.Font.prototype.getName = function() { return this.name_; }; + +/** @override */ +thin.Font.prototype.disposeInternal = function () { + goog.base(this, 'disposeInternal'); + + this.family_ = null; + this.name_ = null; +}; From 789807d848c1ec3a8b6acfa1c382ffb54c5f68ef Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Mon, 7 May 2018 01:20:19 +0900 Subject: [PATCH 15/28] fix typo --- app/editor/base/font.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/editor/base/font.js b/app/editor/base/font.js index 368112cb..6dd95d87 100644 --- a/app/editor/base/font.js +++ b/app/editor/base/font.js @@ -16,7 +16,7 @@ goog.provide('thin.Font'); goog.require('goog.array'); -goog.requrie('goog.Disposable'); +goog.require('goog.Disposable'); goog.require('thin.platform.Font'); From e5fe5d8329f520b1175e8a5f6fb968eaf55296d3 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Mon, 7 May 2018 03:46:02 +0900 Subject: [PATCH 16/28] Show warning in the font option when the font is not installed --- app/assets/fontoption.css | 7 +++++ app/editor/base/font.js | 10 ++++++++ app/editor/ui/combobox.js | 5 ++-- app/editor/ui/fontselect.js | 51 ++++++++++++++++++++++++++++++++++--- app/locales/en.js | 1 + app/locales/ja.js | 1 + app/locales/pt-BR.js | 1 + 7 files changed, 71 insertions(+), 5 deletions(-) diff --git a/app/assets/fontoption.css b/app/assets/fontoption.css index 10586bb5..13619fe8 100644 --- a/app/assets/fontoption.css +++ b/app/assets/fontoption.css @@ -37,6 +37,13 @@ box-sizing: border-box; } +.thin-font-option-invalid .thin-font-option-content { + background-image: url(icons/exclamation-octagon.png); + background-position: 0% 50%; + background-repeat: no-repeat; + padding-left: 18px; +} + /* * FontOptionMenu */ diff --git a/app/editor/base/font.js b/app/editor/base/font.js index 6dd95d87..8570f427 100644 --- a/app/editor/base/font.js +++ b/app/editor/base/font.js @@ -18,6 +18,7 @@ goog.provide('thin.Font'); goog.require('goog.array'); goog.require('goog.Disposable'); goog.require('thin.platform.Font'); +goog.require('thin.platform.FontValidator'); /** @@ -188,6 +189,15 @@ thin.Font.prototype.getName = function() { return this.name_; }; + +/** + * @return {boolean} + */ +thin.Font.prototype.isValid = function () { + return thin.platform.FontValidator.validate(this.family_); +}; + + /** @override */ thin.Font.prototype.disposeInternal = function () { goog.base(this, 'disposeInternal'); diff --git a/app/editor/ui/combobox.js b/app/editor/ui/combobox.js index 8a61e10f..6efcdbe5 100644 --- a/app/editor/ui/combobox.js +++ b/app/editor/ui/combobox.js @@ -296,11 +296,12 @@ thin.ui.ComboBox.prototype.handleInputEditing = function(e) { /** * @param {goog.ui.ControlContent} content * @param {*=} opt_data + * @param {goog.ui.MenuItemRenderer=} opt_renderer * @constructor * @extends {thin.ui.Option} */ -thin.ui.ComboBoxItem = function(content, opt_data) { - thin.ui.Option.call(this, content, opt_data); +thin.ui.ComboBoxItem = function(content, opt_data, opt_renderer) { + thin.ui.Option.call(this, content, opt_data, opt_renderer); }; goog.inherits(thin.ui.ComboBoxItem, thin.ui.Option); diff --git a/app/editor/ui/fontselect.js b/app/editor/ui/fontselect.js index f2d523f3..bc6addfc 100644 --- a/app/editor/ui/fontselect.js +++ b/app/editor/ui/fontselect.js @@ -15,6 +15,7 @@ goog.provide('thin.ui.FontSelect'); goog.provide('thin.ui.FontOptionMenuRenderer'); +goog.provide('thin.ui.FontSelectItem'); goog.require('goog.array'); goog.require('goog.style'); @@ -120,7 +121,7 @@ thin.ui.FontSelect.prototype.loadFonts_ = function () { goog.array.forEach(customFonts, function (font) { - this.addFont_(font); + this.addFont_(font, !font.isValid()); }, this); } } @@ -129,11 +130,13 @@ thin.ui.FontSelect.prototype.loadFonts_ = function () { /** * @param {thin.Font} font + * @param {boolean=} opt_invalid * @private */ -thin.ui.FontSelect.prototype.addFont_ = function(font) { - var item = new thin.ui.ComboBoxItem(font.getFamily()); +thin.ui.FontSelect.prototype.addFont_ = function(font, opt_invalid) { + var item = new thin.ui.FontSelectItem(font, opt_invalid); item.setSticky(true); + this.addItem(item); }; @@ -184,3 +187,45 @@ thin.ui.FontOptionMenuRenderer.CSS_CLASS = thin.ui.FontOptionMenuRenderer.prototype.getCssClass = function() { return thin.ui.FontOptionMenuRenderer.CSS_CLASS; }; + + + +/** + * @param {thin.Font} font + * @param {boolean=} opt_invalid + * @constructor + * @extends {thin.ui.ComboBoxItem} + */ +thin.ui.FontSelectItem = function (font, opt_invalid) { + var renderer = goog.ui.ControlRenderer.getCustomRenderer( + goog.ui.MenuItemRenderer, thin.ui.getCssName(thin.ui.FontSelectItem.CSS_CLASS)); + + goog.base(this, font.getFamily(), null, /** @type {goog.ui.MenuItemRenderer} */(renderer)); + + /** + * @type {boolean?} + * @private + */ + this.invalid_ = opt_invalid; + + if (this.invalid_) { + this.addClassName(thin.ui.getCssName(thin.ui.FontSelectItem.CSS_CLASS, 'invalid')); + } +}; +goog.inherits(thin.ui.FontSelectItem, thin.ui.ComboBoxItem); + + +/** + * @type {string} + */ +thin.ui.FontSelectItem.CSS_CLASS = thin.ui.getCssName('thin-font-option'); + + +/** @override */ +thin.ui.FontSelectItem.prototype.enterDocument = function () { + goog.base(this, 'enterDocument'); + + if (this.invalid_) { + this.getElement().setAttribute('title', thin.t('warning_unavailable_font_not_installed', { family: this.getContent() })); + } +}; diff --git a/app/locales/en.js b/app/locales/en.js index 05cef85a..58b86a99 100644 --- a/app/locales/en.js +++ b/app/locales/en.js @@ -217,6 +217,7 @@ App.addLocale({ notice_no_shapes: 'No shapes', warning_discard_changes: 'If you have unsaved files, the changes will be discarded. Please be sure to save.', warning_discard_changes_en: '', + warning_unavailable_font_not_installed: "{$family} is not available because it won't be installed.", text_editor_force_close_confirmation: 'There are unsaved files. Are you sure you want to close without saving changes?', text_layout_force_close_confirmation: 'This layout has been changed.\nSave before close?', diff --git a/app/locales/ja.js b/app/locales/ja.js index d098c754..dc1f85e0 100644 --- a/app/locales/ja.js +++ b/app/locales/ja.js @@ -217,6 +217,7 @@ App.addLocale({ notice_no_shapes: 'オブジェクトはありません', warning_discard_changes: '保存していないレイアウトがある場合は必ず保存して下さい。', warning_discard_changes_en: 'If you have unsaved files, the changes will be discarded. Please be sure to save.', + warning_unavailable_font_not_installed: '{$family} は利用できません。インストールしてください。', text_editor_force_close_confirmation: '保存されていないファイルがあります。変更を保存せずに閉じても良いですか?', text_layout_force_close_confirmation: '内容が変更されています。\n保存しますか?', diff --git a/app/locales/pt-BR.js b/app/locales/pt-BR.js index 9f83226b..696e9f93 100644 --- a/app/locales/pt-BR.js +++ b/app/locales/pt-BR.js @@ -217,6 +217,7 @@ App.addLocale({ notice_no_shapes: 'Nao ha formas', warning_discard_changes: 'Se voce tiver arquivos que nao foram salvos, as alteracoes serao descartadas.\nPor favor, nao se esqueca de salvar.', warning_discard_changes_en: '', + warning_unavailable_font_not_installed: '{$family} não está disponível porque não será instalada.', text_editor_force_close_confirmation: 'Existem arquivos não salvos. Tem certeza de que deseja fechar sem salvar as alterações?', text_layout_force_close_confirmation: 'Este layout foi alterado. \nSalvar antes de fechar?', From e6527854b4a4a7bdb7a6f27d4f7983d42a55a639 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Wed, 6 Jun 2018 01:51:56 +0900 Subject: [PATCH 17/28] Use yarn also in app --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f6969b2a..be9fe535 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "build": "node tasks/build.js", "release": "cross-env NODE_ENV=production npm run compile && npm run build", "watch": "node tasks/watch.js", - "postinstall": "cd app && npm install" + "postinstall": "cd app && yarn install" }, "devDependencies": { "archiver": "^2.0.3", From aaa6f119aa0cf6ebd4c7e99aed4f403d08301251 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Wed, 6 Jun 2018 01:53:35 +0900 Subject: [PATCH 18/28] Install FontMetrics --- app/package.json | 5 ++++- app/yarn.lock | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 app/yarn.lock diff --git a/app/package.json b/app/package.json index 75c187dc..bbf76812 100644 --- a/app/package.json +++ b/app/package.json @@ -4,5 +4,8 @@ "version": "0.10.0", "license": "GPL-3.0", "description": "Designer for Thinreports", - "main": "main.js" + "main": "main.js", + "dependencies": { + "fontmetrics": "^1.0.0" + } } diff --git a/app/yarn.lock b/app/yarn.lock new file mode 100644 index 00000000..aba14a32 --- /dev/null +++ b/app/yarn.lock @@ -0,0 +1,7 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +fontmetrics@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fontmetrics/-/fontmetrics-1.0.0.tgz#38b205a1eb2e331a77f93fda4028c7037a2869a7" From 28fc56c0724d2d8690c6bb53f99e6f9fd55481b0 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Wed, 6 Jun 2018 02:01:19 +0900 Subject: [PATCH 19/28] Add accesor for FontMetrics --- app/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/index.js b/app/index.js index d721cfaf..4d3225da 100644 --- a/app/index.js +++ b/app/index.js @@ -15,6 +15,7 @@ var App = {}; +App.FontMetrics = require('fontmetrics'); App.handlers = require('./handlers'); /** From 9565c6c38853ecd5a2a4a1039a63ff3067d8dc6b Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Wed, 6 Jun 2018 02:24:05 +0900 Subject: [PATCH 20/28] Implement accessor for App --- app/editor/boot.js | 2 +- app/editor/i18n.js | 6 +++--- app/editor/thin.js | 15 ++++++++++++--- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/app/editor/boot.js b/app/editor/boot.js index 2185590a..85d3b754 100644 --- a/app/editor/boot.js +++ b/app/editor/boot.js @@ -1318,7 +1318,7 @@ thin.init_ = function() { localeSelectBox.setTextAlignLeft(); dialog.addChild(localeSelectBox, false); - var locales = /** @type {Array} */ (thin.callApp('getLocales')); + var locales = /** @type {Array} */ (thin.callAppMethod('getLocales')); goog.array.forEach(locales, function(locale) { localeSelectBox.addItem( diff --git a/app/editor/i18n.js b/app/editor/i18n.js index 1b5872a0..d783284c 100644 --- a/app/editor/i18n.js +++ b/app/editor/i18n.js @@ -147,11 +147,11 @@ thin.i18n.init = function() { var localeId = settings.getLocale(); if (!localeId) { - localeId = /** @type {string} */(thin.callApp('getUILocale')); + localeId = /** @type {string} */(thin.callAppMethod('getUILocale')); settings.setLocale(localeId); } - var locales = /** @type {Array} */(thin.callApp('getLocales')); + var locales = /** @type {Array} */(thin.callAppMethod('getLocales')); var locale = goog.array.find(locales, function(loc) { return loc.id == localeId; }); @@ -163,7 +163,7 @@ thin.i18n.init = function() { i18n.currentLocaleId_ = localeId; i18n.currentLocale_ = locale; - var defaultLocaleId = thin.callApp('getDefaultUILocale'); + var defaultLocaleId = thin.callAppMethod('getDefaultUILocale'); i18n.defaultLocaleId_ = defaultLocaleId; i18n.defaultLocale_ = goog.array.find(locales, function(loc) { return loc.id == defaultLocaleId; diff --git a/app/editor/thin.js b/app/editor/thin.js index c21bd545..ab77384f 100644 --- a/app/editor/thin.js +++ b/app/editor/thin.js @@ -19,13 +19,22 @@ goog.provide('thin.Error'); goog.require('goog.array'); +/** + * @param {string} propertyName + * @return {*} + */ +thin.app = function (propertyName) { + return goog.global['App'][propertyName]; +}; + + /** * Invoke a method of App defined in app.js. * @param {string} appMethodName * @return {*} */ -thin.callApp = function(appMethodName) { - return goog.global['App'][appMethodName](); +thin.callAppMethod = function(appMethodName) { + return thin.app(appMethodName).call(); }; @@ -37,7 +46,7 @@ thin.callApp = function(appMethodName) { */ thin.callAppHandler = function(handlerName, var_args) { var args = goog.array.slice(arguments, 1); - return goog.global['App']['handlers'][handlerName].apply(null, args); + return thin.app('handlers')[handlerName].apply(null, args); } From e1af9450d64746c07342dfd0313ff9a0e65e4ed1 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Thu, 7 Jun 2018 03:07:07 +0900 Subject: [PATCH 21/28] (WIP) Use FontMetrics for calculating font metrics --- app/editor/base/font.js | 32 ++++----- app/editor/base/platform/font.js | 78 +++++----------------- app/editor/core/abstracttext.js | 29 -------- app/editor/core/abstracttextgroup.js | 2 +- app/editor/core/action.js | 6 +- app/editor/core/multipleshapeshelper.js | 3 +- app/editor/core/pagenumberoutline.js | 3 +- app/editor/core/tblockoutline.js | 6 +- app/editor/core/tblockshape.js | 2 +- app/editor/core/texthelper.js | 89 ------------------------- app/editor/core/textshape.js | 14 ++-- 11 files changed, 54 insertions(+), 210 deletions(-) delete mode 100644 app/editor/core/texthelper.js diff --git a/app/editor/base/font.js b/app/editor/base/font.js index 8570f427..5d02b1b0 100644 --- a/app/editor/base/font.js +++ b/app/editor/base/font.js @@ -125,10 +125,7 @@ thin.Font.findFontByFamily = function (family) { * @type {Object.} * @private */ -thin.Font.infoRegistry_ = { - ascent: {}, - height: {} -}; +thin.Font.infoRegistry_ = {}; /** @@ -149,28 +146,33 @@ thin.Font.generateRegistryKey_ = function(var_args) { */ thin.Font.getAscent = function(family, fontSize, isBold) { var registryKey = thin.Font.generateRegistryKey_(family, fontSize, isBold); - var ascent = thin.Font.infoRegistry_.ascent[registryKey]; - if (!goog.isDef(ascent)) { - ascent = thin.platform.Font.getAscent(family, fontSize, isBold); - thin.Font.infoRegistry_.ascent[registryKey] = ascent; + var info = thin.Font.infoRegistry_[registryKey]; + + if (!goog.isDef(info)) { + info = thin.platform.Font.getMetrics(family, fontSize, isBold); + thin.Font.infoRegistry_[registryKey] = info; } - return ascent; + + return info.ascent; }; /** * @param {string} family * @param {number} fontSize + * @param {boolean} isBold * @return {number} */ -thin.Font.getHeight = function(family, fontSize) { +thin.Font.getHeight = function(family, fontSize, isBold) { var registryKey = thin.Font.generateRegistryKey_(family, fontSize); - var height = thin.Font.infoRegistry_.height[registryKey]; - if (!goog.isDef(height)) { - height = thin.platform.Font.getHeight(family, fontSize); - thin.Font.infoRegistry_.height[registryKey] = height; + var info = thin.Font.infoRegistry_[registryKey]; + + if (!goog.isDef(info)) { + info = thin.platform.Font.getMetrics(family, fontSize, isBold); + thin.Font.infoRegistry_[registryKey] = info; } - return height; + + return info.height; }; diff --git a/app/editor/base/platform/font.js b/app/editor/base/platform/font.js index da4fd832..b3d82ed6 100644 --- a/app/editor/base/platform/font.js +++ b/app/editor/base/platform/font.js @@ -17,70 +17,28 @@ goog.provide('thin.platform.Font'); goog.require('goog.dom'); goog.require('thin.platform'); -goog.require('thin.core.TextHelper'); /** - * @type {string} - * @private - */ -thin.platform.FIRST_LINE_TEXT_ = 'Agjぽ'; - - -/** - * @param {string} family - * @param {number} fontSize - * @param {boolean} isBold + * @param {string} family + * @param {number} fontSize + * @param {boolean} isBold * @return {Object} */ -thin.platform.Font.getTextLineSpec = function(family, fontSize, isBold) { - var layout = thin.core.getActiveWorkspace().getLayout(); - - var textHelper = new thin.core.TextHelper(layout); - textHelper.setFontSize(fontSize); - textHelper.setFontFamily(family); - textHelper.setFontBold(isBold); - textHelper.setVisibled(false); - textHelper.setFirstLine(thin.platform.FIRST_LINE_TEXT_); - - var helper = layout.getHelpers(); - helper.appendBack(textHelper); - - var firstLine = textHelper.getFirstLine(); - var spec = { - height: firstLine.getHeight(), - ascent: firstLine.getAscent(), - descent: firstLine.getDescent() +thin.platform.Font.getMetrics = function (family, fontSize, isBold) { + var FontMetrics = thin.app('FontMetrics'); + + var spec = FontMetrics({ + 'fontFamily': family, + 'fontWeight': isBold ? 'bold' : 'normal' + }); + + var ascent = Math.abs(spec.ascent * fontSize); + var descent = Math.abs(spec.descent * fontSize); + + return { + ascent: ascent, + descent: descent, + height: ascent + descent }; - - goog.dom.removeNode(textHelper.getElement()); - // cannot be deleted in ES5 strict mode - firstLine = null; - - return spec; -}; - - -/** - * @param {string} family - * @param {number} fontSize - * @return {number} - */ -thin.platform.Font.getHeight = function(family, fontSize) { - var spec = thin.platform.Font.getTextLineSpec(family, fontSize, false); - return spec.height; -}; - - -/** - * @param {string} family - * @param {number} fontSize - * @param {boolean} isBold - * @return {number} - */ -thin.platform.Font.getAscent = function( - family, fontSize, isBold) { - - var spec = thin.platform.Font.getTextLineSpec(family, fontSize, isBold); - return spec.ascent; }; diff --git a/app/editor/core/abstracttext.js b/app/editor/core/abstracttext.js index 857294fa..3f56ddf6 100644 --- a/app/editor/core/abstracttext.js +++ b/app/editor/core/abstracttext.js @@ -125,32 +125,3 @@ thin.core.AbstractText.prototype.getWidth = function() { this.width_ = this.getBBox().width; return this.width_; }; - - -/** - * @return {number} - */ -thin.core.AbstractText.prototype.getBaseLine = function() { - var element = this.getElement(); - if (element.hasAttribute('y')) { - return Number(this.getLayout().getElementAttribute(element, 'y')); - } else { - return 0; - } -}; - - -/** - * @return {number} - */ -thin.core.AbstractText.prototype.getAscent = function() { - return Math.round(this.getBaseLine() - this.getBBox().y); -}; - - -/** - * @return {number} - */ -thin.core.AbstractText.prototype.getDescent = function() { - return this.getHeight() - this.getAscent(); -}; diff --git a/app/editor/core/abstracttextgroup.js b/app/editor/core/abstracttextgroup.js index e6510bdf..16d0eb2a 100644 --- a/app/editor/core/abstracttextgroup.js +++ b/app/editor/core/abstracttextgroup.js @@ -129,7 +129,7 @@ thin.core.AbstractTextGroup.prototype.setTextLineHeightRatio = function(ratio) { } else { var layout = this.getLayout(); var numRatio = Number(ratio); - var heightAt = thin.Font.getHeight(this.getFontFamily(), this.getFontSize()); + var heightAt = thin.Font.getHeight(this.getFontFamily(), this.getFontSize(), this.isFontBold()); layout.setElementAttributes(element, { 'x-line-height': heightAt * numRatio diff --git a/app/editor/core/action.js b/app/editor/core/action.js index 8cfc352b..d8d16c78 100644 --- a/app/editor/core/action.js +++ b/app/editor/core/action.js @@ -384,7 +384,7 @@ thin.core.Action.prototype.actionSetFontSize = function(newFontSize) { var setFontSizeTblockShape = function(shape, fontSize) { shape.setFontSize(fontSize); if (!shape.isMultiMode()) { - shape.setHeight(thin.Font.getHeight(shape.getFontFamily(), fontSize)); + shape.setHeight(thin.Font.getHeight(shape.getFontFamily(), fontSize, shape.isFontBold())); if (isMultipleSelect) { shape.getTargetOutline().setHeight(shape.getHeight()); } @@ -397,7 +397,7 @@ thin.core.Action.prototype.actionSetFontSize = function(newFontSize) { */ var setPageNumberFontSize = function(shape, fontSize) { shape.setFontSize(fontSize); - shape.setHeight(thin.Font.getHeight(shape.getFontFamily(), fontSize)); + shape.setHeight(thin.Font.getHeight(shape.getFontFamily(), fontSize, shape.isFontBold())); if (isMultipleSelect) { shape.getTargetOutline().setHeight(shape.getHeight()); } @@ -525,7 +525,7 @@ thin.core.Action.prototype.actionSetFontFamily = function(newFontFamily) { var setFontFamilyTblockShape = function(shape, fontFamily) { shape.setFontFamily(fontFamily); if (!shape.isMultiMode()) { - shape.setHeight(thin.Font.getHeight(fontFamily, shape.getFontSize())); + shape.setHeight(thin.Font.getHeight(fontFamily, shape.getFontSize(), shape.isFontBold())); if (isMultipleSelect) { shape.getTargetOutline().setHeight(shape.getHeight()); } diff --git a/app/editor/core/multipleshapeshelper.js b/app/editor/core/multipleshapeshelper.js index 22ef1470..3ce4597a 100644 --- a/app/editor/core/multipleshapeshelper.js +++ b/app/editor/core/multipleshapeshelper.js @@ -867,8 +867,7 @@ thin.core.MultipleShapesHelper.prototype.createPropertyComponent_ = function() { if (shape.instanceOfTblockShape()) { shape.setMultiMode(multipleMode); if (!multipleMode) { - shape.setHeight(thin.Font.getHeight( - shape.getFontFamily(), shape.getFontSize())); + shape.setHeight(thin.Font.getHeight(shape.getFontFamily(), shape.getFontSize(), shape.isFontBold())); shape.getTargetOutline().setHeight(shape.getHeight()); } } diff --git a/app/editor/core/pagenumberoutline.js b/app/editor/core/pagenumberoutline.js index 8cc1c428..413dc3aa 100644 --- a/app/editor/core/pagenumberoutline.js +++ b/app/editor/core/pagenumberoutline.js @@ -50,7 +50,8 @@ thin.core.PageNumberOutline.prototype.setBoundsByCoordinate = function(startPosX thin.numberWithPrecision(Math.abs(startPosX - clientPosX)), thin.Font.getHeight( workspace.getUiStatusForFontFamily(), - workspace.getUiStatusForFontSize())); + workspace.getUiStatusForFontSize(), + workspace.getUiStatusForBold())); this.setBounds(bounds); }; diff --git a/app/editor/core/tblockoutline.js b/app/editor/core/tblockoutline.js index 97255722..ceb56b63 100644 --- a/app/editor/core/tblockoutline.js +++ b/app/editor/core/tblockoutline.js @@ -49,7 +49,9 @@ thin.core.TblockOutline.prototype.setBoundsByCoordinate = function(startPosX, st thin.numberWithPrecision(Math.abs(startPosX - clientPosX)), thin.Font.getHeight( workspace.getUiStatusForFontFamily(), - workspace.getUiStatusForFontSize()))); + workspace.getUiStatusForFontSize(), + workspace.getUiStatusForBold() + ))); }; @@ -107,4 +109,4 @@ thin.core.TblockOutline.prototype.getInitShapeProperties = function() { thin.core.TblockOutline.prototype.disposeInternal = function() { thin.core.TblockOutline.superClass_.disposeInternal.call(this); this.disposeInternalForOutline(); -}; \ No newline at end of file +}; diff --git a/app/editor/core/tblockshape.js b/app/editor/core/tblockshape.js index 6e4cfe03..ab594ae2 100644 --- a/app/editor/core/tblockshape.js +++ b/app/editor/core/tblockshape.js @@ -1071,7 +1071,7 @@ thin.core.TblockShape.prototype.createPropertyComponent_ = function() { scope.setHeight(captureHeight); } else { scope.setHeight(thin.Font.getHeight( - scope.getFontFamily(), scope.getFontSize())); + scope.getFontFamily(), scope.getFontSize(), shape.isFontBold())); } scope.updateToolbarUI(); diff --git a/app/editor/core/texthelper.js b/app/editor/core/texthelper.js deleted file mode 100644 index 2709b05a..00000000 --- a/app/editor/core/texthelper.js +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (C) 2011 Matsukei Co.,Ltd. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -goog.provide('thin.core.TextHelper'); - -goog.require('thin.core.TextLineShape'); -goog.require('thin.core.AbstractTextGroup'); - - -/** - * @param {thin.core.Layout} layout - * @constructor - * @extends {thin.core.AbstractTextGroup} - */ -thin.core.TextHelper = function(layout) { - goog.base(this, this.createElement_(layout), layout); -}; -goog.inherits(thin.core.TextHelper, thin.core.AbstractTextGroup); - - -/** - * @type {thin.core.TextLineShape} - * @private - */ -thin.core.TextHelper.prototype.firstLine_ = null; - -/** - * @param {thin.core.Layout} layout - * @private - */ -thin.core.TextHelper.prototype.createElement_ = function(layout) { - return layout.createSvgElement('g', { - 'stroke-width': 0 - }); -}; - - -/** - * @param {string} content - */ -thin.core.TextHelper.prototype.setFirstLine = function(content) { - goog.array.forEachRight(this.getElement().childNodes, function(element) { - if (element.tagName == 'text') { - goog.dom.removeNode(element); - } - }); - - var layout = this.getLayout(); - var firstLine = new thin.core.TextLineShape( - layout.createSvgElement('text'), layout, 0); - firstLine.setText(content); - layout.appendChild(firstLine, this); - - if (this.firstLine_) { - this.firstLine_.dispose(); - delete this.firstLine_; - } - - this.firstLine_ = firstLine; -}; - - -/** - * @return {thin.core.TextLineShape} - */ -thin.core.TextHelper.prototype.getFirstLine = function() { - return this.firstLine_; -}; - - -/** @inheritDoc */ -thin.core.TextHelper.prototype.disposeInternal = function() { - this.firstLine_.dispose(); - delete this.firstLine_; - - goog.base(this, 'disposeInternal'); -}; diff --git a/app/editor/core/textshape.js b/app/editor/core/textshape.js index 3f907d25..50fdb93d 100644 --- a/app/editor/core/textshape.js +++ b/app/editor/core/textshape.js @@ -202,8 +202,8 @@ thin.core.TextShape.prototype.setTop = function(top) { var isBold = this.isFontBold(); var ascent = thin.Font.getAscent(family, fontSize, isBold); - var heightAt = thin.Font.getHeight(family, fontSize); - var translateY = thin.numberWithPrecision(heightAt * ratio, 2); + var height = thin.Font.getHeight(family, fontSize, isBold); + var translateY = thin.numberWithPrecision(height * ratio, 2); var y = thin.numberWithPrecision(xTop + ascent, 2); goog.array.forEach(this.getTextLineShapes(), function(textline, index) { @@ -257,16 +257,16 @@ thin.core.TextShape.prototype.getHeightInternal = function() { } ratio = Number(ratio); - var heightAt = thin.Font.getHeight(this.getFontFamily(), this.getFontSize()); + var height = thin.Font.getHeight(this.getFontFamily(), this.getFontSize(), this.isFontBold()); var lineCount = this.getTextLineShapes().length; if (ratio >= 1) { - var height = thin.numberWithPrecision((heightAt * ratio) * lineCount); - var diff = thin.numberWithPrecision(heightAt * (ratio - 1), 2); + var height = thin.numberWithPrecision((height * ratio) * lineCount); + var diff = thin.numberWithPrecision(height * (ratio - 1), 2); height = thin.numberWithPrecision(height - diff); } else { - var height = thin.numberWithPrecision(heightAt * lineCount); - var diff = thin.numberWithPrecision(heightAt * (1 - ratio) * (lineCount - 1), 2); + var height = thin.numberWithPrecision(height * lineCount); + var diff = thin.numberWithPrecision(height * (1 - ratio) * (lineCount - 1), 2); height = thin.numberWithPrecision(height - diff); } From 9c1de3410b924080c27b435756d0f84787f0d1fa Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Fri, 8 Jun 2018 10:51:42 +0900 Subject: [PATCH 22/28] Fix height of PageNumber is not applied by changing the font-family --- app/editor/core/action.js | 15 ++------------- app/editor/core/pagenumbershape.js | 12 ++++++++++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/app/editor/core/action.js b/app/editor/core/action.js index d8d16c78..5c31a94e 100644 --- a/app/editor/core/action.js +++ b/app/editor/core/action.js @@ -532,17 +532,6 @@ thin.core.Action.prototype.actionSetFontFamily = function(newFontFamily) { } }; - /** - * @param {thin.core.PageNumberShape} shape - * @param {string} fontFamily - */ - var setPageNumberFontFamily = function(shape, fontFamily) { - shape.setFontFamily(fontFamily); - if (isMultipleSelect) { - shape.getTargetOutline().setBounds(shape.getBounds()); - } - }; - workspace.normalVersioning(function(version) { version.upHandler(function() { layout.forTextShapesEach(shapes, function(shape, i) { @@ -554,7 +543,7 @@ thin.core.Action.prototype.actionSetFontFamily = function(newFontFamily) { }); layout.forPageNumberShapesEach(shapes, function(shape, i) { - setPageNumberFontFamily(shape, newFontFamily); + shape.setFontFamily(newFontFamily); }); if (guide.isEnable()) { @@ -586,7 +575,7 @@ thin.core.Action.prototype.actionSetFontFamily = function(newFontFamily) { }); layout.forPageNumberShapesEach(shapes, function(shape, i) { - setPageNumberFontFamily(shape, pageNumberFontFamilies[i]); + shape.setFontFamily(pageNumberFontFamilies[i]); }); if (guide.isEnable()) { diff --git a/app/editor/core/pagenumbershape.js b/app/editor/core/pagenumbershape.js index 13277c65..3fa1e9f0 100644 --- a/app/editor/core/pagenumbershape.js +++ b/app/editor/core/pagenumbershape.js @@ -249,6 +249,18 @@ thin.core.PageNumberShape.prototype.setOverflowType = function(type) { }; +/** @override */ +thin.core.PageNumberShape.prototype.setFontFamily = function (family) { + goog.base(this, 'setFontFamily', family); + + this.setHeight(thin.Font.getHeight(family, this.getFontSize(), this.isFontBold())); + + if (this.getLayout().getActiveShapeManager().isMultiple()) { + this.getTargetOutline().setBounds(this.getBounds()); + } +}; + + /** * @return {string} */ From 62ec24b8d12aa739e244b9c990a3487a3590f94a Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Fri, 8 Jun 2018 11:32:55 +0900 Subject: [PATCH 23/28] Add anotation --- app/editor/base/platform/font.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/editor/base/platform/font.js b/app/editor/base/platform/font.js index b3d82ed6..428c963c 100644 --- a/app/editor/base/platform/font.js +++ b/app/editor/base/platform/font.js @@ -28,10 +28,12 @@ goog.require('thin.platform'); thin.platform.Font.getMetrics = function (family, fontSize, isBold) { var FontMetrics = thin.app('FontMetrics'); - var spec = FontMetrics({ - 'fontFamily': family, - 'fontWeight': isBold ? 'bold' : 'normal' - }); + var spec = /** @type {Object} */ ( + FontMetrics({ + 'fontFamily': family, + 'fontWeight': isBold ? 'bold' : 'normal' + }) + ); var ascent = Math.abs(spec.ascent * fontSize); var descent = Math.abs(spec.descent * fontSize); From 8e4dcbf80bf0a82b0116d3127562eb4a2ce4c4ab Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Fri, 8 Jun 2018 12:24:13 +0900 Subject: [PATCH 24/28] Add accessor for CustomFontRegistry --- app/editor/core/layout.js | 2 +- app/editor/core/workspace/workspace.js | 13 ++++++++++++- app/editor/ui/fontselect.js | 6 +++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/app/editor/core/layout.js b/app/editor/core/layout.js index dd80dcdb..bd20dae3 100644 --- a/app/editor/core/layout.js +++ b/app/editor/core/layout.js @@ -383,7 +383,7 @@ thin.core.Layout.prototype.createHelpersElement = function(tagName, attrs) { * @return {Array.} */ thin.core.Layout.prototype.getUsedCustomFonts = function () { - var customFonts = this.getWorkspace().customFonts.get(); + var customFonts = this.getWorkspace().getCustomFonts().get(); var allUsedFontFamilies = thin.core.layout.AllUsedFontFamilies.get(this); var usedCustomFonts = goog.array.filter(customFonts, function (font) { diff --git a/app/editor/core/workspace/workspace.js b/app/editor/core/workspace/workspace.js index 1d9f8f28..0616d860 100644 --- a/app/editor/core/workspace/workspace.js +++ b/app/editor/core/workspace/workspace.js @@ -62,8 +62,9 @@ thin.core.Workspace = function(format, opt_file) { /** * @type {thin.core.workspace.CustomFontRegistry} + * @private */ - this.customFonts = new thin.core.workspace.CustomFontRegistry(format.getCustomFonts()); + this.customFonts_ = new thin.core.workspace.CustomFontRegistry(format.getCustomFonts()); /** * @type {string} @@ -356,6 +357,14 @@ thin.core.Workspace.create = function(file) { }; +/** + * @return {thin.core.workspace.CustomFontRegistry} + */ +thin.core.Workspace.prototype.getCustomFonts = function () { + return this.customFonts_; +}; + + /** * @return {boolean} */ @@ -1082,6 +1091,7 @@ thin.core.Workspace.prototype.disposeInternal = function() { delete this.file_; } + this.customFonts_.dispose(); this.action_.dispose(); this.history_.dispose(); @@ -1089,6 +1099,7 @@ thin.core.Workspace.prototype.disposeInternal = function() { delete this.action_; delete this.history_; delete this.layout_; + delete this.customFonts_; goog.base(this, 'disposeInternal'); }; diff --git a/app/editor/ui/fontselect.js b/app/editor/ui/fontselect.js index bc6addfc..22355727 100644 --- a/app/editor/ui/fontselect.js +++ b/app/editor/ui/fontselect.js @@ -61,7 +61,7 @@ thin.ui.FontSelect.prototype.initValidator_ = function () { var workspace = thin.core.getActiveWorkspace(); - if (workspace.customFonts.contains(fontFamily)) { + if (workspace.getCustomFonts().contains(fontFamily)) { return true; } if (thin.platform.FontValidator.validate(fontFamily)) { @@ -92,7 +92,7 @@ thin.ui.FontSelect.prototype.reloadFonts = function () { * @private */ thin.ui.FontSelect.prototype.registerCustomFont_ = function (family) { - var customFontRegistry = thin.core.getActiveWorkspace().customFonts; + var customFontRegistry = thin.core.getActiveWorkspace().getCustomFonts(); if (!customFontRegistry.contains(family)) { customFontRegistry.register(family); @@ -114,7 +114,7 @@ thin.ui.FontSelect.prototype.loadFonts_ = function () { workspace = thin.core.getActiveWorkspace(); if (workspace) { - customFonts = workspace.customFonts.get(); + customFonts = workspace.getCustomFonts().get(); if (!goog.array.isEmpty(customFonts)) { this.addItem(new thin.ui.MenuSeparator()); From c171cfa3d2cd9cf85480a945863c08ca9b7bb578 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Fri, 8 Jun 2018 13:59:59 +0900 Subject: [PATCH 25/28] Revert "Fix height of PageNumber is not applied by changing the font-family" This reverts commit 9c1de3410b924080c27b435756d0f84787f0d1fa. --- app/editor/core/action.js | 15 +++++++++++++-- app/editor/core/pagenumbershape.js | 12 ------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/app/editor/core/action.js b/app/editor/core/action.js index 5c31a94e..d8d16c78 100644 --- a/app/editor/core/action.js +++ b/app/editor/core/action.js @@ -532,6 +532,17 @@ thin.core.Action.prototype.actionSetFontFamily = function(newFontFamily) { } }; + /** + * @param {thin.core.PageNumberShape} shape + * @param {string} fontFamily + */ + var setPageNumberFontFamily = function(shape, fontFamily) { + shape.setFontFamily(fontFamily); + if (isMultipleSelect) { + shape.getTargetOutline().setBounds(shape.getBounds()); + } + }; + workspace.normalVersioning(function(version) { version.upHandler(function() { layout.forTextShapesEach(shapes, function(shape, i) { @@ -543,7 +554,7 @@ thin.core.Action.prototype.actionSetFontFamily = function(newFontFamily) { }); layout.forPageNumberShapesEach(shapes, function(shape, i) { - shape.setFontFamily(newFontFamily); + setPageNumberFontFamily(shape, newFontFamily); }); if (guide.isEnable()) { @@ -575,7 +586,7 @@ thin.core.Action.prototype.actionSetFontFamily = function(newFontFamily) { }); layout.forPageNumberShapesEach(shapes, function(shape, i) { - shape.setFontFamily(pageNumberFontFamilies[i]); + setPageNumberFontFamily(shape, pageNumberFontFamilies[i]); }); if (guide.isEnable()) { diff --git a/app/editor/core/pagenumbershape.js b/app/editor/core/pagenumbershape.js index 3fa1e9f0..13277c65 100644 --- a/app/editor/core/pagenumbershape.js +++ b/app/editor/core/pagenumbershape.js @@ -249,18 +249,6 @@ thin.core.PageNumberShape.prototype.setOverflowType = function(type) { }; -/** @override */ -thin.core.PageNumberShape.prototype.setFontFamily = function (family) { - goog.base(this, 'setFontFamily', family); - - this.setHeight(thin.Font.getHeight(family, this.getFontSize(), this.isFontBold())); - - if (this.getLayout().getActiveShapeManager().isMultiple()) { - this.getTargetOutline().setBounds(this.getBounds()); - } -}; - - /** * @return {string} */ From 36c3fe63e7ccdeb8ef58fbdec511d69810138710 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Fri, 8 Jun 2018 17:56:09 +0900 Subject: [PATCH 26/28] Fix height of PageNumber is not applied by changing the font-family --- app/editor/core/action.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/editor/core/action.js b/app/editor/core/action.js index d8d16c78..e6c57531 100644 --- a/app/editor/core/action.js +++ b/app/editor/core/action.js @@ -538,6 +538,7 @@ thin.core.Action.prototype.actionSetFontFamily = function(newFontFamily) { */ var setPageNumberFontFamily = function(shape, fontFamily) { shape.setFontFamily(fontFamily); + shape.setHeight(thin.Font.getHeight(fontFamily, shape.getFontSize(), shape.isFontBold())); if (isMultipleSelect) { shape.getTargetOutline().setBounds(shape.getBounds()); } From f2912801aa1a53307bb87664d2847ea589cee73c Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Fri, 8 Jun 2018 17:59:42 +0900 Subject: [PATCH 27/28] Add buffer size to text width --- app/editor/core/abstracttext.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/editor/core/abstracttext.js b/app/editor/core/abstracttext.js index 3f56ddf6..a17b593e 100644 --- a/app/editor/core/abstracttext.js +++ b/app/editor/core/abstracttext.js @@ -122,6 +122,6 @@ thin.core.AbstractText.prototype.getHeight = function() { * @return {number} */ thin.core.AbstractText.prototype.getWidth = function() { - this.width_ = this.getBBox().width; + this.width_ = this.getBBox().width * 1.01; return this.width_; }; From 5df288565ed2b5f9725997ff62ef20fba9aac006 Mon Sep 17 00:00:00 2001 From: Katsuya HIDAKA Date: Fri, 8 Jun 2018 18:01:07 +0900 Subject: [PATCH 28/28] =?UTF-8?q?Set=20=E3=81=BD=20as=20char=20for=20calcu?= =?UTF-8?q?lationg=20Ascent=20of=20Font?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/editor/base/platform/font.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/editor/base/platform/font.js b/app/editor/base/platform/font.js index 428c963c..0ae5ce8a 100644 --- a/app/editor/base/platform/font.js +++ b/app/editor/base/platform/font.js @@ -28,6 +28,8 @@ goog.require('thin.platform'); thin.platform.Font.getMetrics = function (family, fontSize, isBold) { var FontMetrics = thin.app('FontMetrics'); + FontMetrics.settings.chars.ascent = 'ぽ'; + var spec = /** @type {Object} */ ( FontMetrics({ 'fontFamily': family,