Commit ce7f7a90 authored by zvorygin@chromium.org's avatar zvorygin@chromium.org

Migrated ComboButton to menu as dropdown.

Added menuItem icon support, and little API for menu modification

BUG=126927
TEST=

Review URL: https://chromiumcodereview.appspot.com/10391184

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@138240 0039d316-1c4b-4281-b951-d872f2087c98
parent 2a26caf6
......@@ -3,79 +3,40 @@
* found in the LICENSE file. */
.buttonbar button.combobutton {
-webkit-box-align: stretch;
display: -webkit-box;
padding-left: 0;
padding-right: 0;
}
.buttonbar .combobutton .task-item div {
padding-left: 7px;
padding-right: 0;
.buttonbar .combobutton > img {
display: block;
height: 16px;
margin-bottom: 6px;
margin-right: 4px;
margin-top: 6px;
width: 16px;
}
.buttonbar .combobutton > span {
-webkit-box-flex: 1;
display: block;
}
.buttonbar .combobutton > div:nth-child(2) {
.buttonbar .combobutton > div {
border-left: solid 1px #dcdcdc;
display: none;
margin-left: 8px;
margin-right: -8px;
width: 22px;
}
.buttonbar .combobutton[multiple] > div:nth-child(2) {
.buttonbar .combobutton[multiple] > div {
display: block;
}
.buttonbar .combobutton > div:nth-child(2) > span.disclosureindicator {
.buttonbar .combobutton > div > span.disclosureindicator {
-webkit-transform: rotate(90deg);
}
.buttonbar .combobutton div.task-item {
line-height: normal;
}
.buttonbar .combobutton .popup {
-webkit-box-align: stretch;
-webkit-box-orient: vertical;
-webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, .50);
background: white;
border: 1px solid rgba(0, 0, 0, 0.25);
border-radius: 2px;
box-sizing: border-box;
color: black;
cursor: default;
display: -webkit-box;
opacity: 0;
padding: 8px 0;
pointer-events: none;
position: absolute;
right: 1px;
white-space: nowrap;
}
.buttonbar .combobutton .popup:active {
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
}
.buttonbar .combobutton[open] .popup {
opacity: 1;
pointer-events: auto;
}
.buttonbar .combobutton .popup > * {
background: transparent;
border: 0;
font: inherit;
overflow: hidden;
text-overflow: ellipsis;
}
.buttonbar .combobutton .popup > *:hover {
background-color: rgb(220, 229, 250);
}
.buttonbar .combobutton .popup > *:active {
background-color: rgb(66, 109, 201);
color: #fff;
}
.buttonbar .combobutton[hidden] {
display: none;
}
\ No newline at end of file
......@@ -201,9 +201,11 @@ menu.chrome-menu {
border-radius: 2px;
outline: none;
padding: 2px 0;
z-index: 15;
}
menu.chrome-menu > :not(hr) {
background-position: 6px center;
background-repeat: no-repeat;
color: rgb(34, 34, 34);
height: 30px;
line-height: 28px;
......@@ -229,7 +231,8 @@ menu.chrome-menu > hr {
}
menu.chrome-menu > :not(hr)[checked] {
background: url('../images/common/check_no_box.png') no-repeat 2px center;
background-image: url('../images/common/check_no_box.png');
background-position: 2px center;
}
menu.chrome-menu > [checked]:before {
......
......@@ -7,155 +7,127 @@
*/
cr.define('cr.ui', function() {
/**
* Sets minWidth for the target, so it's visually as large as source.
* @param {HTMLElement} target Element which min-width to tune.
* @param {HTMLElement} source Element, which width to use.
*/
function enlarge(target, source) {
var cs = target.ownerDocument.defaultView.getComputedStyle(target);
target.style.minWidth = (source.getBoundingClientRect().width -
parseFloat(cs.borderLeftWidth) -
parseFloat(cs.borderRightWidth)) + 'px';
}
/**
* Creates a new combobutton element.
* @param {Object=} opt_propertyBag Optional properties.
* @constructor
* @extends {HTMLUListElement}
*/
var ComboButton = cr.ui.define('div');
var ComboButton = cr.ui.define(cr.ui.MenuButton);
ComboButton.prototype = {
__proto__: HTMLDivElement.prototype,
__proto__: cr.ui.MenuButton.prototype,
defaultItem_: null,
/**
* The items list.
* Truncates drop-down list.
*/
items_: null,
clear: function() {
if (this.items_.length > 0)
// Remove default combobox item if we have added it at addItem.
this.removeChild(this.firstChild);
this.items_ = [];
this.popup_.textContent = '';
this.menu.clear();
this.multiple = false;
this.popup_.style.minWidth = '';
},
addItem: function(item) {
this.items_.push(item);
if (this.items_.length == 1) {
// Set first added item as default on combobox.
// First item should be the first element to prepend drop-down arrow and
// popup layer.
this.insertBefore(item, this.firstChild);
addDropDownItem: function(item) {
this.multiple = true;
this.menu.addMenuItem(item).data = item;
},
/**
* Default item to fire on combobox click
*/
get defaultItem() {
return this.defaultItem_;
},
set defaultItem(defaultItem) {
this.defaultItem_ = defaultItem;
if (defaultItem.label) {
this.labelNode_.textContent = defaultItem.label;
} else {
this.multiple = true;
if (this.popup_.hasChildNodes())
this.popup_.insertBefore(item, this.popup_.firstChild);
else
this.popup_.appendChild(item);
if (this.visible)
this.setPopupSize_();
this.labelNode_.textContent = '';
}
},
setPopupSize_: function() {
this.popup_.style.bottom = (this.clientHeight + 1) + 'px';
enlarge(this.popup_, this);
if (defaultItem.iconUrl) {
this.iconNode_.src = defaultItem.iconUrl;
} else {
this.iconNode_.src = '';
}
},
/**
* Initializes the element.
*/
decorate: function() {
this.items_ = [];
cr.ui.MenuButton.prototype.decorate.call(this);
this.classList.add('combobutton');
this.iconNode_ = this.ownerDocument.createElement('img');
this.appendChild(this.iconNode_);
this.labelNode_ = this.ownerDocument.createElement('span');
this.appendChild(this.labelNode_);
var triggerIcon = this.ownerDocument.createElement('span');
triggerIcon.className = 'disclosureindicator';
this.trigger_ = this.ownerDocument.createElement('div');
this.trigger_.appendChild(triggerIcon);
this.popup_ = this.ownerDocument.createElement('div');
this.popup_.className = 'popup';
this.appendChild(this.trigger_);
this.appendChild(this.popup_);
this.addEventListener('click',
this.handleButtonClick_.bind(this));
this.popup_.addEventListener('click',
this.handlePopupClick_.bind(this));
this.addEventListener('click', this.handleButtonClick_.bind(this));
this.trigger_.addEventListener('click',
this.handleTriggerClicked_.bind(this));
this.addEventListener('mouseout', this.handleMouseOut_.bind(this));
this.visible = true;
},
this.menu.addEventListener('activate',
this.handleMenuActivate_.bind(this));
handleTriggerClicked_: function(event) {
this.open = !this.open;
event.stopPropagation();
// Remove mousedown event listener created by MenuButton::decorate,
// and move it down to trigger_.
this.removeEventListener('mousedown', this);
this.trigger_.addEventListener('mousedown', this);
},
handleMouseOut_: function(event) {
var x = event.x;
var y = event.y;
var children = this.childNodes;
for (var i = 0; i < children.length; i++)
{
var r = this.children[i].getBoundingClientRect();
if (x >= r.left && x <= r.right && y >= r.top && y <= r.bottom)
return;
/**
* Handles the keydown event for the menu button.
*/
handleKeyDown: function(e) {
switch (e.keyIdentifier) {
case 'Down':
case 'Up':
if (!this.isMenuShown())
this.showMenu();
e.preventDefault();
break;
case 'Esc':
case 'U+001B': // Maybe this is remote desktop playing a prank?
this.hideMenu();
break;
}
this.open = false;
},
handleButtonClick_: function(event) {
this.dispatchSelectEvent(this.items_[0]);
handleTriggerClicked_: function(event) {
event.stopPropagation();
},
handlePopupClick_: function(event) {
var item = event.target;
while (item && item.parentNode != this.popup_)
item = item.parentNode;
if (!item)
return;
handleMenuActivate_: function(event) {
this.dispatchSelectEvent(event.target.data);
},
this.open = false;
this.dispatchSelectEvent(item);
event.stopPropagation();
handleButtonClick_: function() {
this.dispatchSelectEvent(this.defaultItem_);
},
dispatchSelectEvent: function(item) {
var selectEvent = new Event('select');
selectEvent.item = item;
this.dispatchEvent(selectEvent);
},
get visible() {
return this.hasAttribute('visible');
},
set visible(value) {
if (value) {
this.setAttribute('visible', 'visible');
setTimeout(this.setPopupSize_.bind(this), 0);
} else {
this.removeAttribute('visible');
}
}
};
cr.defineProperty(ComboButton, 'disabled', cr.PropertyKind.BOOL_ATTR);
cr.defineProperty(ComboButton, 'open', cr.PropertyKind.BOOL_ATTR);
cr.defineProperty(ComboButton, 'multiple', cr.PropertyKind.BOOL_ATTR);
return {
......
......@@ -2498,6 +2498,15 @@ FileManager.prototype = {
return this.metadataProvider_;
};
/**
* Creates combobox item based on task.
* @param {Object} task Task to convert.
* @return {Object} Item appendable to combobox drop-down list.
*/
FileManager.prototype.createComboboxItem_ = function(task) {
return { label: task.title, iconUrl: task.iconUrl, task: task };
}
/**
* Callback called when tasks for selected files are determined.
* @param {Object} selection Selection is passed here, since this.selection
......@@ -2508,7 +2517,8 @@ FileManager.prototype = {
this.taskItems_.clear();
var defaultTask = null;
var tasksCount = 0;
var dropDownItems = [];
for (var i = 0; i < tasksList.length; i++) {
var task = tasksList[i];
......@@ -2567,15 +2577,27 @@ FileManager.prototype = {
task.title = str('INSTALL_CRX');
}
}
this.taskItems_.addItem(this.renderTaskItem_(task));
tasksCount++;
if (defaultTask == null) defaultTask = task;
if (defaultTask == null) {
defaultTask = task;
this.taskItems_.defaultItem = this.createComboboxItem_(task);
task.title = task.title + ' ' + str('DEFAULT_ACTION_LABEL');
dropDownItems.push(this.createComboboxItem_(task));
} else {
dropDownItems.push(this.createComboboxItem_(task));
}
}
this.taskItems_.hidden = tasksCount == 0;
if (tasksCount > 1) {
// Duplicate default task in drop-down list.
this.taskItems_.addItem(this.renderTaskItem_(defaultTask));
this.taskItems_.hidden = dropDownItems.length == 0;
if (dropDownItems.length > 1) {
dropDownItems.sort(function(a, b) {
return a.label.localeCompare(b.label);
});
for (var j = 0; j < dropDownItems.length; j++) {
this.taskItems_.addDropDownItem(dropDownItems[j]);
}
}
selection.tasksList = tasksList;
......@@ -2586,22 +2608,6 @@ FileManager.prototype = {
}
};
FileManager.prototype.renderTaskItem_ = function(task) {
var item = this.document_.createElement('div');
item.className = 'task-item';
item.task = task;
var img = this.document_.createElement('img');
img.src = task.iconUrl;
item.appendChild(img);
var label = this.document_.createElement('div');
label.appendChild(this.document_.createTextNode(task.title));
item.appendChild(label);
return item;
};
FileManager.prototype.getExtensionId_ = function() {
return chrome.extension.getURL('').split('/')[2];
};
......
......@@ -123,6 +123,9 @@
i18n-content=GDATA_SHOW_HOSTED_FILES_OPTION></menuitem>
</menu>
<menu id="tasks-menu" class="chrome-menu">
</menu>
<div class=dialog-title invisibleif='full-page'>[TITLE]</div>
<div class=dialog-container>
<div class=dialog-sidebar>
......@@ -151,7 +154,7 @@
</div>
<button class="menubutton" id="gdata-settings"
menu="#docs-settings" visibleif="full-page">
<img src="images/settings.svg" alt="Settings">
<img src="images/settings.svg">
<span class="disclosureindicator"></span>
</button>
</div>
......@@ -178,7 +181,8 @@
</div>
<div class=preview-summary></div>
<div class="right buttonbar" visibleif="full-page">
<button id="tasks" class="combobutton"></button>
<button id="tasks" class="combobutton" menu="#tasks-menu">
</button>
<button id="delete-button" command="#delete"
i18n-content="DELETE_BUTTON_LABEL">
</button>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment