mirror of https://github.com/node-red/node-red.git
commit
372c0ea690
|
|
@ -538,7 +538,7 @@ var RED = (function() {
|
|||
node.dirty = true;
|
||||
RED.view.redrawStatus(node);
|
||||
}
|
||||
});
|
||||
})
|
||||
RED.comms.subscribe("notification/plugin/#",function(topic,msg) {
|
||||
if (topic == "notification/plugin/added") {
|
||||
RED.settings.refreshSettings(function(err, data) {
|
||||
|
|
@ -669,12 +669,12 @@ var RED = (function() {
|
|||
RED.eventLog.log(id,payload);
|
||||
});
|
||||
|
||||
$(".red-ui-header-toolbar").show();
|
||||
loader.end();
|
||||
|
||||
$(".red-ui-header-toolbar").removeClass('hide');
|
||||
RED.sidebar.show(":first", true);
|
||||
|
||||
setTimeout(function() {
|
||||
loader.end();
|
||||
checkTelemetry(function () {
|
||||
checkFirstRun(function() {
|
||||
if (showProjectWelcome) {
|
||||
|
|
@ -893,6 +893,7 @@ var RED = (function() {
|
|||
RED.comms.connect();
|
||||
|
||||
$("#red-ui-main-container").show();
|
||||
setTimeout(() => $("#red-ui-header-tabs").show(), 100)
|
||||
RED.events.emit("sidebar:resize")
|
||||
|
||||
loadPluginList();
|
||||
|
|
@ -901,14 +902,18 @@ var RED = (function() {
|
|||
|
||||
|
||||
function buildEditor(options) {
|
||||
var header = $('<div id="red-ui-header"></div>').appendTo(options.target);
|
||||
var logo = $('<span class="red-ui-header-logo"></span>').appendTo(header);
|
||||
const header = $('<div id="red-ui-header"></div>').appendTo(options.target);
|
||||
const logoContainer = $('<div id="red-ui-header-logo"></div>').appendTo(header);
|
||||
let logo = $('<span class="red-ui-header-logo"></span>').appendTo(logoContainer);
|
||||
$('<div id="red-ui-header-tabs" class="hide"></div>').appendTo(header);
|
||||
$('<ul class="red-ui-header-toolbar hide"></ul>').appendTo(header);
|
||||
$('<div id="red-ui-header-shade" class="hide"></div>').appendTo(header);
|
||||
$('<div id="red-ui-main-container">'+
|
||||
'<div id="red-ui-sidebar-left"></div>'+
|
||||
'<div id="red-ui-workspace"></div>'+
|
||||
'<div id="red-ui-sidebar"></div>'+
|
||||
'<div id="red-ui-sidebar-container">'+
|
||||
'<div id="red-ui-sidebar"></div>'+
|
||||
'</div>'+
|
||||
'<div id="red-ui-editor-stack" tabindex="-1"></div>'+
|
||||
'</div>').appendTo(options.target);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,16 @@ RED.settings = (function () {
|
|||
}
|
||||
};
|
||||
|
||||
var set = function (key, value) {
|
||||
/**
|
||||
* Set a setting in the user settings within the runtime.
|
||||
* Calls to this function are debounced to avoid excessive calls to the runtime when multiple settings are changed in quick succession.
|
||||
* The flush parameter can be set to true to bypass the debounce and immediately save the settings to the runtime.
|
||||
* @param {string} key
|
||||
* @param {*} value
|
||||
* @param {boolean} flush
|
||||
* @returns
|
||||
*/
|
||||
var set = function (key, value, flush) {
|
||||
if (!hasLocalStorage()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -37,7 +46,7 @@ RED.settings = (function () {
|
|||
localStorage.setItem(key+this.authTokensSuffix, JSON.stringify(value));
|
||||
} else {
|
||||
RED.utils.setMessageProperty(userSettings,key,value);
|
||||
saveUserSettings();
|
||||
saveUserSettings(flush);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -188,13 +197,12 @@ RED.settings = (function () {
|
|||
});
|
||||
}
|
||||
|
||||
function saveUserSettings() {
|
||||
function saveUserSettings(flush) {
|
||||
if (RED.user.hasPermission("settings.write")) {
|
||||
if (pendingSave) {
|
||||
clearTimeout(pendingSave);
|
||||
}
|
||||
pendingSave = setTimeout(function() {
|
||||
pendingSave = null;
|
||||
const save = () => {
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
|
|
@ -206,7 +214,15 @@ RED.settings = (function () {
|
|||
console.log("Unexpected error saving user settings:",jqXHR.status,textStatus);
|
||||
}
|
||||
});
|
||||
},300);
|
||||
}
|
||||
if (flush) {
|
||||
save()
|
||||
} else {
|
||||
pendingSave = setTimeout(function() {
|
||||
pendingSave = null;
|
||||
save();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ RED.tabs = (function() {
|
|||
var currentActiveTabWidth = 0;
|
||||
var collapsibleMenu;
|
||||
var mousedownTab;
|
||||
var mouseclickTab;
|
||||
var preferredOrder = options.order;
|
||||
var ul = options.element || $("#"+options.id);
|
||||
var wrapper = ul.wrap( "<div>" ).parent();
|
||||
|
|
@ -39,6 +40,34 @@ RED.tabs = (function() {
|
|||
wrapper.addClass("red-ui-tabs-vertical");
|
||||
}
|
||||
|
||||
var scrollLeft;
|
||||
var scrollRight;
|
||||
|
||||
if (options.scrollable) {
|
||||
wrapper.addClass("red-ui-tabs-scrollable");
|
||||
scrollContainer.addClass("red-ui-tabs-scroll-container");
|
||||
scrollContainer.on("scroll",function(evt) {
|
||||
// Generated by trackpads - not mousewheel
|
||||
updateScroll(evt);
|
||||
});
|
||||
scrollContainer.on("wheel", function(evt) {
|
||||
if (evt.originalEvent.deltaX === 0) {
|
||||
// Prevent the scroll event from firing
|
||||
evt.preventDefault();
|
||||
|
||||
// Assume this is wheel event which might not trigger
|
||||
// the scroll event, so do things manually
|
||||
var sl = scrollContainer.scrollLeft();
|
||||
sl += evt.originalEvent.deltaY;
|
||||
scrollContainer.scrollLeft(sl);
|
||||
}
|
||||
})
|
||||
scrollLeft = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-left" style="display:none;"><a href="#"><i class="fa fa-caret-left"></i></a></div>').prependTo(wrapper).find("a");
|
||||
scrollLeft.on('mousedown',function(evt) {scrollEventHandler(evt, evt.shiftKey?('-='+scrollContainer.scrollLeft()):'-=150') }).on('click',function(evt){ evt.preventDefault();});
|
||||
scrollRight = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-right"><a href="#" style="display:none;"><i class="fa fa-caret-right"></i></a></div>').appendTo(wrapper).find("a");
|
||||
scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,evt.shiftKey?('+='+(scrollContainer[0].scrollWidth - scrollContainer.width()-scrollContainer.scrollLeft())):'+=150') }).on('click',function(evt){ evt.preventDefault();});
|
||||
}
|
||||
|
||||
if (options.addButton) {
|
||||
wrapper.addClass("red-ui-tabs-add");
|
||||
var addButton = $('<div class="red-ui-tab-button red-ui-tabs-add"><a href="#"><i class="fa fa-plus"></i></a></div>').appendTo(wrapper);
|
||||
|
|
@ -165,34 +194,6 @@ RED.tabs = (function() {
|
|||
})
|
||||
}
|
||||
|
||||
var scrollLeft;
|
||||
var scrollRight;
|
||||
|
||||
if (options.scrollable) {
|
||||
wrapper.addClass("red-ui-tabs-scrollable");
|
||||
scrollContainer.addClass("red-ui-tabs-scroll-container");
|
||||
scrollContainer.on("scroll",function(evt) {
|
||||
// Generated by trackpads - not mousewheel
|
||||
updateScroll(evt);
|
||||
});
|
||||
scrollContainer.on("wheel", function(evt) {
|
||||
if (evt.originalEvent.deltaX === 0) {
|
||||
// Prevent the scroll event from firing
|
||||
evt.preventDefault();
|
||||
|
||||
// Assume this is wheel event which might not trigger
|
||||
// the scroll event, so do things manually
|
||||
var sl = scrollContainer.scrollLeft();
|
||||
sl += evt.originalEvent.deltaY;
|
||||
scrollContainer.scrollLeft(sl);
|
||||
}
|
||||
})
|
||||
scrollLeft = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-left"><a href="#" style="display:none;"><i class="fa fa-caret-left"></i></a></div>').appendTo(wrapper).find("a");
|
||||
scrollLeft.on('mousedown',function(evt) {scrollEventHandler(evt, evt.shiftKey?('-='+scrollContainer.scrollLeft()):'-=150') }).on('click',function(evt){ evt.preventDefault();});
|
||||
scrollRight = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-right"><a href="#" style="display:none;"><i class="fa fa-caret-right"></i></a></div>').appendTo(wrapper).find("a");
|
||||
scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,evt.shiftKey?('+='+(scrollContainer[0].scrollWidth - scrollContainer.width()-scrollContainer.scrollLeft())):'+=150') }).on('click',function(evt){ evt.preventDefault();});
|
||||
}
|
||||
|
||||
if (options.collapsible) {
|
||||
// var dropDown = $('<div>',{class:"red-ui-tabs-select"}).appendTo(wrapper);
|
||||
// ul.hide();
|
||||
|
|
@ -299,11 +300,12 @@ RED.tabs = (function() {
|
|||
return;
|
||||
}
|
||||
mousedownTab = null;
|
||||
if (dblClickTime && Date.now()-dblClickTime < 400) {
|
||||
if (dblClickTime && Date.now()-dblClickTime < 400 && evt.currentTarget === mouseclickTab) {
|
||||
dblClickTime = 0;
|
||||
dblClickArmed = true;
|
||||
return onTabDblClick.call(this,evt);
|
||||
}
|
||||
mouseclickTab = evt.currentTarget
|
||||
dblClickTime = Date.now();
|
||||
|
||||
var currentTab = ul.find("li.red-ui-tab.active");
|
||||
|
|
@ -382,11 +384,12 @@ RED.tabs = (function() {
|
|||
var scWidth = scrollContainer.width();
|
||||
var ulWidth = ul.width();
|
||||
if (sl === 0) {
|
||||
scrollLeft.hide();
|
||||
// We use the parent of the LH button so it doesn't take up space when hidden
|
||||
scrollLeft.parent().hide();
|
||||
} else {
|
||||
scrollLeft.show();
|
||||
scrollLeft.parent().show();
|
||||
}
|
||||
if (sl === ulWidth-scWidth) {
|
||||
if (Math.abs(sl - Math.round(ulWidth-scWidth)) < 5) {
|
||||
scrollRight.hide();
|
||||
} else {
|
||||
scrollRight.show();
|
||||
|
|
@ -403,7 +406,6 @@ RED.tabs = (function() {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function activateTab(link) {
|
||||
if (typeof link === "string") {
|
||||
link = ul.find("a[href='#"+link+"']");
|
||||
|
|
@ -418,6 +420,7 @@ RED.tabs = (function() {
|
|||
}
|
||||
}
|
||||
if (!link.parent().hasClass("active")) {
|
||||
updateTabWidths();
|
||||
ul.children().removeClass("active");
|
||||
ul.children().css({"transition": "width 100ms"});
|
||||
link.parent().addClass("active");
|
||||
|
|
@ -425,6 +428,8 @@ RED.tabs = (function() {
|
|||
wrapper.find(".red-ui-tab-link-button").removeClass("active selected");
|
||||
$("#"+parentId+"-link-button").addClass("active selected");
|
||||
if (options.scrollable) {
|
||||
window.sc = scrollContainer;
|
||||
window.at = link
|
||||
var pos = link.parent().position().left;
|
||||
if (pos-21 < 0) {
|
||||
scrollContainer.animate( { scrollLeft: '+='+(pos-50) }, 300);
|
||||
|
|
@ -435,7 +440,6 @@ RED.tabs = (function() {
|
|||
if (options.onchange) {
|
||||
options.onchange(tabs[link.attr('href').slice(1)]);
|
||||
}
|
||||
updateTabWidths();
|
||||
setTimeout(function() {
|
||||
ul.children().css({"transition": ""});
|
||||
},100);
|
||||
|
|
@ -467,7 +471,7 @@ RED.tabs = (function() {
|
|||
var allTabs = ul.find("li.red-ui-tab");
|
||||
var tabs = allTabs.filter(":not(.hide-tab)");
|
||||
var hiddenTabs = allTabs.filter(".hide-tab");
|
||||
var width = wrapper.width();
|
||||
var width = options.scrollable ? scrollContainer.width() : wrapper.width();
|
||||
var tabCount = tabs.length;
|
||||
var tabWidth;
|
||||
|
||||
|
|
@ -509,20 +513,20 @@ RED.tabs = (function() {
|
|||
tabs.css({width:tabWidth});
|
||||
|
||||
} else {
|
||||
var tabWidth = (width-12-(tabCount*6))/tabCount;
|
||||
var tabWidth = Math.round((width-12-(tabCount*6))/tabCount);
|
||||
currentTabWidth = (100*tabWidth/width)+"%";
|
||||
currentActiveTabWidth = currentTabWidth+"%";
|
||||
if (options.scrollable) {
|
||||
tabWidth = Math.max(tabWidth,140);
|
||||
currentTabWidth = tabWidth+"px";
|
||||
currentActiveTabWidth = 0;
|
||||
var listWidth = Math.max(wrapper.width(),12+(tabWidth+6)*tabCount);
|
||||
var listWidth = Math.max(scrollContainer.width(),12+(tabWidth+6)*tabCount);
|
||||
ul.width(listWidth);
|
||||
updateScroll();
|
||||
} else if (options.hasOwnProperty("minimumActiveTabWidth")) {
|
||||
if (tabWidth < options.minimumActiveTabWidth) {
|
||||
tabCount -= 1;
|
||||
tabWidth = (width-12-options.minimumActiveTabWidth-(tabCount*6))/tabCount;
|
||||
tabWidth = Math.round((width-12-options.minimumActiveTabWidth-(tabCount*6))/tabCount);
|
||||
currentTabWidth = (100*tabWidth/width)+"%";
|
||||
currentActiveTabWidth = options.minimumActiveTabWidth+"px";
|
||||
} else {
|
||||
|
|
@ -964,7 +968,9 @@ RED.tabs = (function() {
|
|||
activateTab: activateTab,
|
||||
nextTab: activateNextTab,
|
||||
previousTab: activatePreviousTab,
|
||||
resize: updateTabWidths,
|
||||
resize: function () {
|
||||
updateTabWidths()
|
||||
},
|
||||
count: function() {
|
||||
return ul.find("li.red-ui-tab:not(.hide)").length;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
**/
|
||||
RED.sidebar = (function() {
|
||||
const sidebarLayoutVersion = 1
|
||||
const sidebarLayoutVersion = 3
|
||||
const sidebars = {
|
||||
primary: {
|
||||
id: 'primary',
|
||||
|
|
@ -37,16 +37,26 @@ RED.sidebar = (function() {
|
|||
}
|
||||
}
|
||||
const defaultSidebarConfiguration = {
|
||||
primary: [ ['info','help','config','context'], ['debug'] ],
|
||||
secondary: [ ['explorer'], ['palette'] ]
|
||||
v: sidebarLayoutVersion,
|
||||
primary: { top: { tabs: ['info','help','config','context'], active: 'info' }, bottom: { tabs: ['debug'], active: 'debug' } },
|
||||
secondary: { top: { tabs: ['explorer'], active: 'explorer' }, bottom: { tabs: ['palette'], active: 'palette' } }
|
||||
}
|
||||
|
||||
let lastSessionSelectedTabs = {}
|
||||
|
||||
const knownTabs = {};
|
||||
|
||||
let sidebarsInitialised = false
|
||||
|
||||
function exportSidebarState () {
|
||||
if (!sidebars.secondary?.tabBars?.bottom?.container) {
|
||||
// This has been called whilst setting up the sidebars
|
||||
// We don't have all the state yet, so not nothing to export
|
||||
return
|
||||
}
|
||||
const state = {
|
||||
primary: [[], []],
|
||||
secondary: [[], []],
|
||||
primary: { top: { tabs: [] }, bottom: { tabs: [] } },
|
||||
secondary: { top: { tabs: [] }, bottom: { tabs: [] } },
|
||||
v: sidebarLayoutVersion
|
||||
}
|
||||
function getTabButtons(tabBar) {
|
||||
|
|
@ -59,22 +69,32 @@ RED.sidebar = (function() {
|
|||
})
|
||||
return result
|
||||
}
|
||||
state.primary[0] = getTabButtons(sidebars.primary.tabBars.top.container);
|
||||
state.primary[1] = getTabButtons(sidebars.primary.tabBars.bottom.container);
|
||||
state.secondary[0] = getTabButtons(sidebars.secondary.tabBars.top.container);
|
||||
state.secondary[1] = getTabButtons(sidebars.secondary.tabBars.bottom.container);
|
||||
state.primary.top.tabs = getTabButtons(sidebars.primary.tabBars.top.container);
|
||||
state.primary.bottom.tabs = getTabButtons(sidebars.primary.tabBars.bottom.container);
|
||||
state.secondary.top.tabs = getTabButtons(sidebars.secondary.tabBars.top.container);
|
||||
state.secondary.bottom.tabs = getTabButtons(sidebars.secondary.tabBars.bottom.container);
|
||||
|
||||
RED.settings.set('editor.sidebar.state', state)
|
||||
state.primary.top.hidden = !!sidebars.primary.sections.top.hidden
|
||||
state.primary.bottom.hidden = !!sidebars.primary.sections.bottom.hidden
|
||||
state.secondary.top.hidden = !!sidebars.secondary.sections.top.hidden
|
||||
state.secondary.bottom.hidden = !!sidebars.secondary.sections.bottom.hidden
|
||||
|
||||
state.primary.top.active = sidebars.primary.tabBars.top.active
|
||||
state.primary.bottom.active = sidebars.primary.tabBars.bottom.active
|
||||
state.secondary.top.active = sidebars.secondary.tabBars.top.active
|
||||
state.secondary.bottom.active = sidebars.secondary.tabBars.bottom.active
|
||||
|
||||
const newState = JSON.stringify(state)
|
||||
const existingState = JSON.stringify(RED.settings.get('editor.sidebar.state'))
|
||||
if (newState !== existingState) {
|
||||
RED.settings.set('editor.sidebar.state', state)
|
||||
}
|
||||
if (state.secondary.top.tabs.length === 0) {
|
||||
console.warn('wiped the floor')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We store the current sidebar tab id in localStorage as 'last-sidebar-tab'
|
||||
// This is restored when the editor is reloaded.
|
||||
// We use sidebars.primary.tabs.onchange to update localStorage. However that will
|
||||
// also get triggered when the first tab gets added to the tabs - typically
|
||||
// the 'info' tab. So we use the following variable to store the retrieved
|
||||
// value from localStorage before we start adding the actual tabs
|
||||
let lastSessionSelectedTabs = {}
|
||||
|
||||
function addTab(title,content,closeable,visible) {
|
||||
var options;
|
||||
|
|
@ -96,39 +116,39 @@ RED.sidebar = (function() {
|
|||
|
||||
// Check the saved sidebar state to see if this tab should be added to the primary or secondary sidebar
|
||||
let savedState = RED.settings.get('editor.sidebar.state', defaultSidebarConfiguration)
|
||||
if (typeof savedState.primary[0] === 'string' || typeof savedState.secondary[0] === 'string' || savedState.v === undefined) {
|
||||
// This is a beta.0/1 format. Reset it for beta.2
|
||||
savedState = defaultSidebarConfiguration
|
||||
RED.settings.set('editor.sidebar.state', savedState)
|
||||
}
|
||||
|
||||
let targetSidebar = null
|
||||
let targetSection = null
|
||||
let showSection = true
|
||||
if (savedState) {
|
||||
let sidebarState
|
||||
if (savedState.secondary[0].includes(options.id)) {
|
||||
if (savedState.secondary.top.tabs.includes(options.id)) {
|
||||
options.target = 'secondary'
|
||||
sidebarState = savedState.secondary[0]
|
||||
sidebarState = savedState.secondary.top
|
||||
targetSidebar = sidebars.secondary
|
||||
targetSection = 'top'
|
||||
} else if (savedState.secondary[1].includes(options.id)) {
|
||||
} else if (savedState.secondary.bottom.tabs.includes(options.id)) {
|
||||
options.target = 'secondary'
|
||||
sidebarState = savedState.secondary[1]
|
||||
sidebarState = savedState.secondary.bottom
|
||||
targetSidebar = sidebars.secondary
|
||||
targetSection = 'bottom'
|
||||
} else if (savedState.primary[0].includes(options.id)) {
|
||||
} else if (savedState.primary.top.tabs.includes(options.id)) {
|
||||
options.target = 'primary'
|
||||
sidebarState = savedState.primary[0]
|
||||
sidebarState = savedState.primary.top
|
||||
targetSidebar = sidebars.primary
|
||||
targetSection = 'top'
|
||||
} else if (savedState.primary[1].includes(options.id)) {
|
||||
} else if (savedState.primary.bottom.tabs.includes(options.id)) {
|
||||
options.target = 'primary'
|
||||
sidebarState = savedState.primary[1]
|
||||
sidebarState = savedState.primary.bottom
|
||||
targetSidebar = sidebars.primary
|
||||
targetSection = 'bottom'
|
||||
}
|
||||
if (targetSidebar) {
|
||||
if (sidebarState.hidden) {
|
||||
showSection = false
|
||||
}
|
||||
// This tab was found in the saved sidebar state. Now find the target position for the tab button
|
||||
targetTabButtonIndex = sidebarState.indexOf(options.id)
|
||||
targetTabButtonIndex = sidebarState.tabs.indexOf(options.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -189,22 +209,27 @@ RED.sidebar = (function() {
|
|||
return
|
||||
}
|
||||
const targetSidebar = options.target === 'secondary' ? sidebars.secondary : sidebars.primary;
|
||||
//
|
||||
if (targetSidebar.tabBars[options.targetSection].active === options.id && RED.menu.isSelected(targetSidebar.menuToggle)) {
|
||||
// if (!targetSidebar.sections[options.targetSection].hidden) {
|
||||
// targetSidebar.hideSection(options.targetSection)
|
||||
// } else {
|
||||
// targetSidebar.showSection(options.targetSection)
|
||||
// }
|
||||
RED.menu.setSelected(targetSidebar.menuToggle, false);
|
||||
if (!targetSidebar.sections[options.targetSection].hidden) {
|
||||
const otherSectionHidden = targetSidebar.sections[options.targetSection === 'top' ? 'bottom' : 'top'].hidden
|
||||
if (otherSectionHidden) {
|
||||
// Both sections are going to be hidden, so hide the sidebar first.
|
||||
// We do this *before* hiding the last section so that we remember which the 'last' section was and it can be
|
||||
// restored when the sidebar is shown again.
|
||||
RED.menu.setSelected(targetSidebar.menuToggle, false);
|
||||
} else {
|
||||
// Hiding just one section, clear its active setting
|
||||
targetSidebar.tabBars[targetSection].active = null
|
||||
}
|
||||
targetSidebar.hideSection(options.targetSection)
|
||||
} else {
|
||||
targetSidebar.showSection(options.targetSection)
|
||||
}
|
||||
exportSidebarState()
|
||||
} else {
|
||||
RED.sidebar.show(options.id)
|
||||
}
|
||||
})
|
||||
if (targetSidebar.sections[targetSection].content.children().length === 1) {
|
||||
RED.sidebar.show(options.id)
|
||||
}
|
||||
targetSidebar.resizeSidebarTabBar()
|
||||
}
|
||||
|
||||
function removeTab(id) {
|
||||
|
|
@ -243,9 +268,16 @@ RED.sidebar = (function() {
|
|||
if (targetSidebar.sections[targetPosition].content.children().length === 1) {
|
||||
RED.sidebar.show(options.id)
|
||||
}
|
||||
if (srcSidebar.sections[srcPosition].content.children().length === 0 && srcPosition === 'bottom') {
|
||||
if (srcSidebar.sections[srcPosition].content.children().length === 0) {
|
||||
// src has been emptied
|
||||
srcSidebar.hideSection(srcPosition)
|
||||
} else if (targetSidebar.sections[targetPosition].hidden) {
|
||||
srcSidebar.tabBars[srcPosition].container.addClass('red-ui-sidebar-tab-bar-empty')
|
||||
}
|
||||
if (targetSidebar.sections[targetPosition].content.children().length > 0) {
|
||||
targetSidebar.tabBars[targetPosition].container.removeClass('red-ui-sidebar-tab-bar-empty')
|
||||
}
|
||||
|
||||
if (targetSidebar.sections[targetPosition].hidden) {
|
||||
targetSidebar.showSection(targetPosition)
|
||||
}
|
||||
}
|
||||
|
|
@ -255,33 +287,44 @@ RED.sidebar = (function() {
|
|||
function setupSidebarTabs(sidebar) {
|
||||
const tabBar = $('<div class="red-ui-sidebar-tab-bar"></div>').addClass('red-ui-sidebar-' + sidebar.direction);
|
||||
if (sidebar.direction === 'right') {
|
||||
tabBar.insertAfter(sidebar.container);
|
||||
tabBar.appendTo("#red-ui-workspace-footer");
|
||||
} else if (sidebar.direction === 'left') {
|
||||
tabBar.insertBefore(sidebar.container);
|
||||
tabBar.prependTo("#red-ui-workspace-footer");
|
||||
}
|
||||
|
||||
// TODO: make this an API object, not just a jQuery object
|
||||
// TODO: consider an explicit toggle button for the sidebars...
|
||||
// const toggleSidebarButton = $('<button class="red-ui-sidebar-toggle-button"><i class="fa fa-columns"></i></button>')
|
||||
// toggleSidebarButton.on('click', function() {
|
||||
// RED.menu.toggleSelected(sidebar.menuToggle);
|
||||
// })
|
||||
sidebar.tabBars = {
|
||||
top: setupTabSection(sidebar, tabBar, 'top'),
|
||||
bottom: setupTabSection(sidebar, tabBar, 'bottom')
|
||||
}
|
||||
sidebar.tabBar = sidebar.tabBars.top.container;
|
||||
sidebar.resizeSidebarTabBar = function () {
|
||||
sidebar.tabBars.top.resizeSidebarTabBar();
|
||||
sidebar.tabBars.bottom.resizeSidebarTabBar();
|
||||
}
|
||||
// if (sidebar.direction === 'right') {
|
||||
// toggleSidebarButton.appendTo(tabBar);
|
||||
// } else if (sidebar.direction === 'left') {
|
||||
// toggleSidebarButton.prependTo(tabBar);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
sidebar.tabBar = tabBar // sidebar.tabBars.top.container;
|
||||
sidebar.hideSection = function (position) {
|
||||
// Track the height of the top section as that is the one that will determine the layout - but only if the other section is visible.
|
||||
const otherPosition = position === 'top' ? 'bottom' : 'top'
|
||||
if (!sidebar.sections[otherPosition].hidden) {
|
||||
sidebar.sections.top.height = sidebar.sections.top.container.height() || 300
|
||||
}
|
||||
sidebar.sections[position].container.hide()
|
||||
sidebar.sections[position].hidden = true
|
||||
|
||||
const otherPosition = position === 'top' ? 'bottom' : 'top'
|
||||
sidebar.sections[otherPosition].container.css('flex-grow', '1')
|
||||
|
||||
if (otherPosition === 'bottom') {
|
||||
sidebar.sections[otherPosition].container.css('margin-top', sidebar.direction === 'left' ? '0' : '4px')
|
||||
}
|
||||
sidebar.tabBars[position].clearSelected()
|
||||
// sidebar.tabBars.top.container.css('flex-grow', '1')
|
||||
// sidebar.tabBars[position].container.css('flex-grow', '0')
|
||||
// sidebar.tabBars[position].container.css('height', '60px')
|
||||
|
||||
|
||||
sidebar.resizeSidebar()
|
||||
}
|
||||
sidebar.showSection = function (position) {
|
||||
|
|
@ -289,15 +332,16 @@ RED.sidebar = (function() {
|
|||
sidebar.sections[position].hidden = false
|
||||
const otherPosition = position === 'top' ? 'bottom' : 'top'
|
||||
sidebar.sections[otherPosition].container.css('flex-grow', '0')
|
||||
sidebar.sections[otherPosition].container.css('height', '70%')
|
||||
// sidebar.tabBars.top.container.css('flex-grow', '')
|
||||
// sidebar.tabBars[position].container.css('flex-grow', '')
|
||||
// sidebar.tabBars[position].container.css('height', '')
|
||||
// sidebar.tabBars[position].active
|
||||
sidebar.sections.top.container.css('height', sidebar.sections.top.height + 'px')
|
||||
sidebar.sections.bottom.container.css('height', '100%')
|
||||
if (otherPosition === 'bottom') {
|
||||
sidebar.sections[otherPosition].container.css('margin-top', '')
|
||||
}
|
||||
sidebar.tabBars[position].container.find('button[data-tab-id="'+sidebar.tabBars[position].active+'"]').addClass('selected')
|
||||
|
||||
sidebar.resizeSidebar()
|
||||
}
|
||||
sidebar.hideSection('top')
|
||||
sidebar.hideSection('bottom')
|
||||
}
|
||||
|
||||
function setupTabSection(sidebar, tabBar, position) {
|
||||
|
|
@ -349,6 +393,7 @@ RED.sidebar = (function() {
|
|||
tabBarButtonsContainer.data('sidebar', sidebar.id)
|
||||
tabBarButtonsContainer.data('sidebar-position', position)
|
||||
tabBarButtonsContainer.sortable({
|
||||
axis: 'x',
|
||||
distance: 10,
|
||||
cancel: false,
|
||||
items: "button:not(.red-ui-sidebar-tab-bar-overflow-button)",
|
||||
|
|
@ -356,14 +401,6 @@ RED.sidebar = (function() {
|
|||
connectWith: ".red-ui-sidebar-tab-bar-buttons",
|
||||
start: function(event, ui) {
|
||||
const tabId = ui.item.attr('data-tab-id');
|
||||
const tabCount = tabBarButtonsContainer.children('button:not(.red-ui-sidebar-tab-bar-overflow-button):not(.red-ui-sidebar-tab-bar-button-placeholder)').length
|
||||
if (position === 'top' && tabCount === 1) {
|
||||
// Call in a timeout to allow the stortable start event to complete
|
||||
// processing - otherwise errors are thrown
|
||||
setTimeout(function () {
|
||||
tabBarButtonsContainer.sortable('cancel');
|
||||
}, 0);
|
||||
}
|
||||
const options = knownTabs[tabId];
|
||||
options.tabButtonTooltip.delete()
|
||||
draggingTabButton = true
|
||||
|
|
@ -395,59 +432,10 @@ RED.sidebar = (function() {
|
|||
RED.sidebar.show(firstTab);
|
||||
}
|
||||
}
|
||||
src.resizeSidebarTabBar();
|
||||
dest.resizeSidebarTabBar();
|
||||
|
||||
RED.sidebar.show(tabId)
|
||||
}
|
||||
})
|
||||
|
||||
let hasHidden = false
|
||||
const resizeSidebarTabBar = function () {
|
||||
let tabBarButtonsBottom = tabBarButtonsContainer.position().top + tabBarButtonsContainer.outerHeight();
|
||||
const buttonHeight = tabOverflowButton.outerHeight()
|
||||
// Find the last visible button
|
||||
let bottomButton = tabBarButtonsContainer.children(":visible").last()
|
||||
if (bottomButton.length === 0) {
|
||||
// Nothing visible - bail out
|
||||
return
|
||||
}
|
||||
if (tabBarButtonsBottom < bottomButton.position().top + buttonHeight) {
|
||||
tabOverflowButton.show()
|
||||
let tabOverflowButtonBottom = tabOverflowButton.position().top + buttonHeight * 1.5;
|
||||
while (tabBarButtonsBottom < tabOverflowButtonBottom) {
|
||||
const lastVisible = tabBarButtonsContainer.children(':not(".red-ui-sidebar-tab-bar-overflow-button"):visible').last()
|
||||
if (lastVisible.length === 0) {
|
||||
// Nothing left to hide
|
||||
break
|
||||
}
|
||||
lastVisible.hide()
|
||||
tabOverflowButtonBottom = tabOverflowButton.position().top + buttonHeight * 1.5;
|
||||
}
|
||||
} else {
|
||||
const hiddenChildren = tabBarButtonsContainer.children(':not(".red-ui-sidebar-tab-bar-overflow-button"):hidden')
|
||||
if (hiddenChildren.length > 0) {
|
||||
// We may be able to show some more buttons
|
||||
let tabOverflowButtonBottom = tabOverflowButton.position().top + buttonHeight * 2;
|
||||
let shownCount = 0
|
||||
while (tabBarButtonsBottom > tabOverflowButtonBottom + buttonHeight) {
|
||||
const firstHidden = tabBarButtonsContainer.children(':not(".red-ui-sidebar-tab-bar-overflow-button"):hidden').first()
|
||||
if (firstHidden.length === 0) {
|
||||
// Nothing left to show
|
||||
break
|
||||
}
|
||||
firstHidden.show()
|
||||
shownCount++
|
||||
tabOverflowButtonBottom = tabOverflowButton.position().top + buttonHeight * 2;
|
||||
}
|
||||
if (hiddenChildren.length - shownCount <= 0) {
|
||||
// We were able to show all of the hidden buttons
|
||||
// so hide the overflow button again
|
||||
tabOverflowButton.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
container: tabBarButtonsContainer,
|
||||
addButton: function(button, position) {
|
||||
|
|
@ -459,8 +447,7 @@ RED.sidebar = (function() {
|
|||
},
|
||||
clearSelected: function() {
|
||||
tabBarButtonsContainer.children('button').removeClass('selected')
|
||||
},
|
||||
resizeSidebarTabBar
|
||||
}
|
||||
}
|
||||
}
|
||||
function setupSidebarSeparator(sidebar) {
|
||||
|
|
@ -526,8 +513,7 @@ RED.sidebar = (function() {
|
|||
}
|
||||
sidebar.container.width(newSidebarWidth);
|
||||
ui.position.left -= scaleFactor * d
|
||||
|
||||
// sidebar.tabs.resize();
|
||||
sidebar.tabBar.css('min-width', sidebar.container.width() - 5)
|
||||
RED.events.emit("sidebar:resize");
|
||||
},
|
||||
stop:function(event,ui) {
|
||||
|
|
@ -537,12 +523,13 @@ RED.sidebar = (function() {
|
|||
if (sidebar.menuToggle) {
|
||||
RED.menu.setSelected(sidebar.menuToggle,false);
|
||||
}
|
||||
sidebar.container.hide()
|
||||
sidebar.sections.top.container.hide()
|
||||
sidebar.sections.bottom.container.hide()
|
||||
sidebar.separator.hide()
|
||||
if (sidebar.container.width() < sidebar.minimumWidth) {
|
||||
sidebar.container.width(sidebar.defaultWidth);
|
||||
}
|
||||
} else {
|
||||
sidebar.width = sidebar.container.width();
|
||||
}
|
||||
sidebar.tabBar.css('min-width', sidebar.container.width() - 5)
|
||||
RED.events.emit("sidebar:resize");
|
||||
}
|
||||
});
|
||||
|
|
@ -551,17 +538,47 @@ RED.sidebar = (function() {
|
|||
|
||||
function toggleSidebar(sidebar, state) {
|
||||
if (!state) {
|
||||
sidebar.container.hide()
|
||||
// sidebar.container.hide()
|
||||
sidebar.separator.hide()
|
||||
sidebar.tabBars.top.clearSelected()
|
||||
sidebar.tabBars.bottom.clearSelected()
|
||||
// Remember which sections were hidden (or not) before we hide the sidebar - so we can restore that state when we show the sidebar again
|
||||
sidebar.sections.top.wasHidden = sidebar.sections.top.hidden
|
||||
sidebar.sections.bottom.wasHidden = sidebar.sections.bottom.hidden
|
||||
sidebar.hideSection('top')
|
||||
sidebar.hideSection('bottom')
|
||||
sidebar.container.width(0)
|
||||
if (sidebarsInitialised) {
|
||||
exportSidebarState()
|
||||
}
|
||||
} else {
|
||||
sidebar.container.show()
|
||||
// sidebar.container.show()
|
||||
if (!sidebar.sections.top.hidden) {
|
||||
|
||||
sidebar.sections.top.container.show()
|
||||
}
|
||||
if (!sidebar.sections.bottom.hidden) {
|
||||
sidebar.sections.bottom.container.show()
|
||||
}
|
||||
if (sidebar.sections.top.hidden && sidebar.sections.bottom.hidden) {
|
||||
const topHasContent = sidebar.sections.top.content.children().length > 0
|
||||
const bottomHasContent = sidebar.sections.bottom.content.children().length > 0
|
||||
if (!topHasContent && !bottomHasContent) {
|
||||
// Nothing to show - keep the sidebar hidden
|
||||
return
|
||||
}
|
||||
if (sidebar.tabBars.top.active) {
|
||||
showSidebar(sidebar.tabBars.top.active)
|
||||
}
|
||||
if (sidebar.tabBars.bottom.active) {
|
||||
showSidebar(sidebar.tabBars.bottom.active)
|
||||
}
|
||||
}
|
||||
sidebar.container.width(sidebar.width || sidebar.defaultWidth)
|
||||
sidebar.tabBar.css('min-width', sidebar.container.width() - 5)
|
||||
sidebar.separator.show()
|
||||
if (sidebar.tabBars.top.active) {
|
||||
if (sidebar.tabBars.top.active && !sidebar.sections.top.hidden) {
|
||||
sidebar.tabBars.top.container.find('button[data-tab-id="'+sidebar.tabBars.top.active+'"]').addClass('selected')
|
||||
}
|
||||
if (sidebar.tabBars.bottom.active) {
|
||||
if (sidebar.tabBars.bottom.active && !sidebar.sections.bottom.hidden) {
|
||||
sidebar.tabBars.bottom.container.find('button[data-tab-id="'+sidebar.tabBars.bottom.active+'"]').addClass('selected')
|
||||
}
|
||||
}
|
||||
|
|
@ -570,15 +587,17 @@ RED.sidebar = (function() {
|
|||
|
||||
function showSidebar(id, skipShowSidebar) {
|
||||
if (id === ":first") {
|
||||
sidebarsInitialised = true
|
||||
// Show the last selected tab for each sidebar
|
||||
Object.keys(sidebars).forEach(function(sidebarKey) {
|
||||
const sidebar = sidebars[sidebarKey];
|
||||
['top','bottom'].forEach(function(position) {
|
||||
let lastTabId = lastSessionSelectedTabs[sidebarKey + '-' + position];
|
||||
if (!lastTabId) {
|
||||
lastTabId = sidebar.tabBars[position].container.children('button').first().attr('data-tab-id');
|
||||
if (lastSessionSelectedTabs[sidebarKey]?.[position]?.hidden !== true) {
|
||||
let lastTabId = lastSessionSelectedTabs[sidebarKey]?.[position]?.active;
|
||||
if (lastTabId) {
|
||||
showSidebar(lastTabId)
|
||||
}
|
||||
}
|
||||
showSidebar(lastTabId, true)
|
||||
})
|
||||
})
|
||||
return
|
||||
|
|
@ -600,17 +619,18 @@ RED.sidebar = (function() {
|
|||
} else {
|
||||
targetSidebar.sections[targetSection].footer.hide();
|
||||
}
|
||||
RED.settings.setLocal("last-sidebar-tab-" + targetSidebar.id+'-'+targetSection, tabOptions.id)
|
||||
// TODO: find which tabBar the button is in
|
||||
targetSidebar.tabBars[targetSection].clearSelected()
|
||||
targetSidebar.tabBars[targetSection].container.find('button[data-tab-id="'+id+'"]').addClass('selected')
|
||||
targetSidebar.tabBars[targetSection].active = id
|
||||
if (!skipShowSidebar && targetSidebar.sections[targetSection].hidden) {
|
||||
targetSidebar.showSection(targetSection)
|
||||
}
|
||||
if (!skipShowSidebar && !RED.menu.isSelected(targetSidebar.menuToggle)) {
|
||||
RED.menu.setSelected(targetSidebar.menuToggle,true);
|
||||
}
|
||||
if (targetSidebar.sections[targetSection].hidden) {
|
||||
targetSidebar.showSection(targetSection)
|
||||
if (!targetSidebar.sections[targetSection].hidden) {
|
||||
targetSidebar.tabBars[targetSection].clearSelected()
|
||||
targetSidebar.tabBars[targetSection].container.find('button[data-tab-id="'+id+'"]').addClass('selected')
|
||||
}
|
||||
exportSidebarState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -666,7 +686,7 @@ RED.sidebar = (function() {
|
|||
return
|
||||
}
|
||||
sidebar.sections.top.container.outerHeight(startTopSectionHeight + delta)
|
||||
sidebar.tabBars.top.container.outerHeight(startTopTabSectionHeight + delta)
|
||||
// sidebar.tabBars.top.container.outerHeight(startTopTabSectionHeight + delta)
|
||||
ui.position.top -= delta
|
||||
lastSeparatorPosition = ui.position.top
|
||||
sidebar.resizeSidebar()
|
||||
|
|
@ -678,7 +698,6 @@ RED.sidebar = (function() {
|
|||
// sidebar.shade = $('<div class="red-ui-sidebar-shade hide"></div>').appendTo(sidebar.container);
|
||||
|
||||
sidebar.separator = setupSidebarSeparator(sidebar);
|
||||
setupSidebarTabs(sidebar)
|
||||
sidebar.resizeSidebar = function () {
|
||||
// Resize sidebar sections as needed
|
||||
const topSectionHeight = sidebar.sections.top.container.outerHeight()
|
||||
|
|
@ -689,23 +708,15 @@ RED.sidebar = (function() {
|
|||
if (bottomSectionHeight < 90 && topSectionHeight > 90) {
|
||||
sidebar.sections.top.container.outerHeight(topSectionHeight - (90 - bottomSectionHeight));
|
||||
}
|
||||
sidebar.tabBars.top.container.height(sidebar.sections.top.container.outerHeight())
|
||||
// } else {
|
||||
// sidebar.tabBars.top.container.height(sidebar.sections.top.container.outerHeight() - 60)
|
||||
}
|
||||
// Trigger a resize of the tab bars to handle overflow
|
||||
sidebar.resizeSidebarTabBar()
|
||||
sidebar.tabBar.css('min-width', sidebar.container.width() - 5)
|
||||
RED.events.emit("sidebar:resize");
|
||||
|
||||
}
|
||||
$(window).on("resize", sidebar.resizeSidebar)
|
||||
if (sidebar.defaultTopHeight > 0) {
|
||||
if (sidebar.defaultTopHeight === 1) {
|
||||
sidebar.hideSection('bottom')
|
||||
} else {
|
||||
sidebar.sections.top.container.outerHeight(sidebarHeight * sidebar.defaultTopHeight);
|
||||
}
|
||||
}
|
||||
|
||||
setupSidebarTabs(sidebar)
|
||||
sidebar.resizeSidebar()
|
||||
|
||||
}
|
||||
|
|
@ -727,15 +738,25 @@ RED.sidebar = (function() {
|
|||
RED.menu.toggleSelected(sidebars.secondary.menuToggle);
|
||||
} else {
|
||||
toggleSidebar(sidebars.secondary, state);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Remember the last selected tab for each sidebar before
|
||||
// the tabs are readded causing the state to get updated
|
||||
Object.keys(sidebars).forEach(function(sidebarKey) {
|
||||
lastSessionSelectedTabs[sidebarKey + '-top'] = RED.settings.getLocal("last-sidebar-tab-" + sidebarKey + '-top');
|
||||
lastSessionSelectedTabs[sidebarKey + '-bottom'] = RED.settings.getLocal("last-sidebar-tab-" + sidebarKey + '-bottom');
|
||||
})
|
||||
// Load any saved sidebar state
|
||||
lastSessionSelectedTabs = RED.settings.get('editor.sidebar.state', defaultSidebarConfiguration)
|
||||
if (typeof lastSessionSelectedTabs.primary[0] === 'string' || typeof lastSessionSelectedTabs.secondary[0] === 'string' || lastSessionSelectedTabs.v === undefined || lastSessionSelectedTabs.v !== sidebarLayoutVersion) {
|
||||
// This is a beta.0/1 format. Reset it for beta.2
|
||||
lastSessionSelectedTabs = defaultSidebarConfiguration
|
||||
// To migrate state format, we have to delete the old entry rather than try to merge settings
|
||||
// RED.settings.set debounces calls made within 300ms - we need the above call to get flushed before setting the new state value.
|
||||
RED.settings.set('editor.sidebar.state', null, true)
|
||||
RED.settings.set('editor.sidebar.state', lastSessionSelectedTabs)
|
||||
}
|
||||
|
||||
// Restore the active flags so we know which sidebars to show when the :first option is used
|
||||
sidebars.primary.tabBars.top.active = lastSessionSelectedTabs?.primary?.top?.active
|
||||
sidebars.primary.tabBars.bottom.active = lastSessionSelectedTabs?.primary?.bottom?.active
|
||||
sidebars.secondary.tabBars.top.active = lastSessionSelectedTabs?.secondary?.top?.active
|
||||
sidebars.secondary.tabBars.bottom.active = lastSessionSelectedTabs?.secondary?.bottom?.active
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@
|
|||
|
||||
RED.statusBar = (function() {
|
||||
|
||||
var widgets = {};
|
||||
var leftBucket;
|
||||
var rightBucket;
|
||||
const widgets = {};
|
||||
let leftBucket;
|
||||
let rightBucket;
|
||||
|
||||
function addWidget(options) {
|
||||
widgets[options.id] = options;
|
||||
|
|
@ -59,8 +59,9 @@ RED.statusBar = (function() {
|
|||
|
||||
return {
|
||||
init: function() {
|
||||
leftBucket = $('<span class="red-ui-statusbar-bucket red-ui-statusbar-bucket-left">').appendTo("#red-ui-workspace-footer");
|
||||
rightBucket = $('<span class="red-ui-statusbar-bucket red-ui-statusbar-bucket-right">').appendTo("#red-ui-workspace-footer");
|
||||
const widgetBar = $('<div id="red-ui-statusbar">').appendTo("#red-ui-workspace-footer")
|
||||
leftBucket = $('<span class="red-ui-statusbar-bucket red-ui-statusbar-bucket-left">').appendTo(widgetBar);
|
||||
rightBucket = $('<span class="red-ui-statusbar-bucket red-ui-statusbar-bucket-right">').appendTo(widgetBar);
|
||||
},
|
||||
add: addWidget,
|
||||
hide: hideWidget,
|
||||
|
|
|
|||
|
|
@ -446,13 +446,13 @@ RED.subflow = (function() {
|
|||
|
||||
refreshToolbar(activeSubflow);
|
||||
|
||||
$("#red-ui-workspace-chart").css({"margin-top": "40px"});
|
||||
$("#red-ui-workspace-chart").addClass('red-ui-workspace-toolbar-active');
|
||||
$("#red-ui-workspace-toolbar").show();
|
||||
}
|
||||
|
||||
function hideWorkspaceToolbar() {
|
||||
$("#red-ui-workspace-toolbar").hide().empty();
|
||||
$("#red-ui-workspace-chart").css({"margin-top": "0"});
|
||||
$("#red-ui-workspace-chart").removeClass('red-ui-workspace-toolbar-active');
|
||||
}
|
||||
function deleteSubflow(id) {
|
||||
const subflow = RED.nodes.subflow(id || RED.workspaces.active());
|
||||
|
|
|
|||
|
|
@ -58,47 +58,36 @@ RED.sidebar.info = (function() {
|
|||
"display": "flex",
|
||||
"flex-direction": "column"
|
||||
}).appendTo(stackContainer);
|
||||
propertiesPanelHeader = $("<div>", {class:"red-ui-palette-header red-ui-info-header"}).css({
|
||||
propertiesPanelHeader = $("<div>", {class:"red-ui-sidebar-header"}).css({
|
||||
"flex":"0 0 auto"
|
||||
}).appendTo(propertiesPanel);
|
||||
|
||||
propertiesPanelHeaderIcon = $("<span>").appendTo(propertiesPanelHeader);
|
||||
propertiesPanelHeaderLabel = $("<span>").appendTo(propertiesPanelHeader);
|
||||
propertiesPanelHeaderIcon = $('<span style="display: flex; align-items: center;"></span>').appendTo(propertiesPanelHeader);
|
||||
propertiesPanelHeaderLabel = $('<span style="overflow: hidden; text-overflow: ellipsis; flex: 1 1 auto;"></span>').appendTo(propertiesPanelHeader);
|
||||
|
||||
propertiesPanelHeaderCopyLink = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-link"></button>').css({
|
||||
position: 'absolute',
|
||||
top: '6px',
|
||||
right: '32px'
|
||||
}).on("click", function(evt) {
|
||||
const buttons = $('<span class="button-group"></span>').appendTo(propertiesPanelHeader);
|
||||
propertiesPanelHeaderCopyLink = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-link"></button>').on("click", function(evt) {
|
||||
RED.actions.invoke('core:copy-item-url',selectedObject)
|
||||
}).appendTo(propertiesPanelHeader);
|
||||
}).appendTo(buttons);
|
||||
RED.popover.tooltip(propertiesPanelHeaderCopyLink,RED._("sidebar.info.copyItemUrl"));
|
||||
|
||||
propertiesPanelHeaderHelp = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-book"></button>').css({
|
||||
position: 'absolute',
|
||||
top: '6px',
|
||||
right: '56px'
|
||||
}).on("click", function(evt) {
|
||||
propertiesPanelHeaderHelp = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-book"></button>').on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
if (selectedObject) {
|
||||
RED.sidebar.help.show(selectedObject.type);
|
||||
}
|
||||
}).appendTo(propertiesPanelHeader);
|
||||
}).appendTo(buttons);
|
||||
RED.popover.tooltip(propertiesPanelHeaderHelp,RED._("sidebar.help.showHelp"));
|
||||
|
||||
propertiesPanelHeaderReveal = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-search"></button>').css({
|
||||
position: 'absolute',
|
||||
top: '6px',
|
||||
right: '8px'
|
||||
}).on("click", function(evt) {
|
||||
propertiesPanelHeaderReveal = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-search"></button>').on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
if (selectedObject) {
|
||||
RED.sidebar.info.outliner.reveal(selectedObject);
|
||||
RED.view.reveal(selectedObject.id);
|
||||
}
|
||||
}).appendTo(propertiesPanelHeader);
|
||||
}).appendTo(buttons);
|
||||
RED.popover.tooltip(propertiesPanelHeaderReveal,RED._("sidebar.help.showInOutline"));
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@
|
|||
|
||||
function handleWindowResize() {
|
||||
let sidebarWidth = $("#red-ui-sidebar").is(":visible") ? $("#red-ui-sidebar").outerWidth() : 0;
|
||||
$("#red-ui-editor-stack").css('right', sidebarWidth + $("#red-ui-sidebar + .red-ui-sidebar-tab-bar").outerWidth() + 4);
|
||||
$("#red-ui-editor-stack").css('right', sidebarWidth + 4);
|
||||
if (stack.length > 0) {
|
||||
var tray = stack[stack.length-1];
|
||||
if (tray.options.maximized || tray.width > $("#red-ui-editor-stack").position().left-8) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
|
||||
RED.view.navigator = (function() {
|
||||
var nav_scale = 50;
|
||||
var nav_scale = 80;
|
||||
var nav_width = 8000/nav_scale;
|
||||
var nav_height = 8000/nav_scale;
|
||||
var navContainer;
|
||||
|
|
@ -45,8 +45,8 @@ RED.view.navigator = (function() {
|
|||
navNode.each(function(d) {
|
||||
d3.select(this).attr("x",function(d) { return (d.x-d.w/2)/nav_scale })
|
||||
.attr("y",function(d) { return (d.y-d.h/2)/nav_scale })
|
||||
.attr("width",function(d) { return Math.max(9,d.w/nav_scale) })
|
||||
.attr("height",function(d) { return Math.max(3,d.h/nav_scale) })
|
||||
.attr("width",function(d) { return Math.max(4,d.w/nav_scale) })
|
||||
.attr("height",function(d) { return Math.max(2,d.h/nav_scale) })
|
||||
.attr("fill",function(d) { return RED.utils.getNodeColor(d.type,d._def);})
|
||||
});
|
||||
}
|
||||
|
|
@ -129,12 +129,19 @@ RED.view.navigator = (function() {
|
|||
$(window).on("resize", resizeNavBorder);
|
||||
RED.events.on("sidebar:resize",resizeNavBorder);
|
||||
RED.actions.add("core:toggle-navigator",toggle);
|
||||
|
||||
RED.statusBar.add({
|
||||
id: "view-navigator",
|
||||
align: "left",
|
||||
element: $('<span id="red-ui-view-navigator-widget" style="position: relative;"><button class="red-ui-footer-button-toggle single" id="red-ui-view-navigate"><i class="fa fa-map-o"></i></button></span>')
|
||||
})
|
||||
|
||||
navContainer = $('<div>').css({
|
||||
"position":"absolute",
|
||||
"bottom":$("#red-ui-workspace-footer").height() + 12,
|
||||
"right": 16,
|
||||
"bottom": 35,
|
||||
"left": 0,
|
||||
zIndex: 1
|
||||
}).addClass('red-ui-navigator-container').appendTo("#red-ui-workspace").hide();
|
||||
}).addClass('red-ui-navigator-container').appendTo("#red-ui-view-navigator-widget").hide();
|
||||
navBox = d3.select(navContainer[0])
|
||||
.append("svg:svg")
|
||||
.attr("width", nav_width)
|
||||
|
|
@ -169,6 +176,7 @@ RED.view.navigator = (function() {
|
|||
navBorder.attr('x',newX).attr('y',newY);
|
||||
$("#red-ui-workspace-chart").scrollLeft(newX*nav_scale*scaleFactor);
|
||||
$("#red-ui-workspace-chart").scrollTop(newY*nav_scale*scaleFactor);
|
||||
RED.events.emit("view:navigate");
|
||||
}).on("mouseup", function() {
|
||||
isDragging = false;
|
||||
}).on("mouseenter", function () {
|
||||
|
|
@ -183,11 +191,7 @@ RED.view.navigator = (function() {
|
|||
}
|
||||
})
|
||||
navBorder = navBox.append("rect").attr("class","red-ui-navigator-border")
|
||||
RED.statusBar.add({
|
||||
id: "view-navigator",
|
||||
align: "right",
|
||||
element: $('<button class="red-ui-footer-button-toggle single" id="red-ui-view-navigate"><i class="fa fa-map-o"></i></button>')
|
||||
})
|
||||
|
||||
|
||||
$("#red-ui-view-navigate").on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
|
|
|
|||
|
|
@ -738,6 +738,7 @@ RED.view = (function() {
|
|||
chart.scrollLeft(0);
|
||||
chart.scrollTop(0);
|
||||
}
|
||||
RED.events.emit("view:navigate");
|
||||
var scrollDeltaLeft = chart.scrollLeft() - scrollStartLeft;
|
||||
var scrollDeltaTop = chart.scrollTop() - scrollStartTop;
|
||||
if (mouse_position != null) {
|
||||
|
|
@ -765,42 +766,6 @@ RED.view = (function() {
|
|||
}
|
||||
})
|
||||
|
||||
RED.statusBar.add({
|
||||
id: "view-zoom-controls",
|
||||
align: "right",
|
||||
element: $('<span class="button-group">'+
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-zoom-out"><i class="fa fa-minus"></i></button>'+
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-zoom-zero"><i class="fa fa-circle-o"></i></button>'+
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-zoom-in"><i class="fa fa-plus"></i></button>'+
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-zoom-fit"><i class="fa fa-compress"></i></button>'+
|
||||
'</span>')
|
||||
})
|
||||
|
||||
$("#red-ui-view-zoom-out").on("click", function() { zoomOut(); });
|
||||
RED.popover.tooltip($("#red-ui-view-zoom-out"),RED._('actions.zoom-out'),'core:zoom-out');
|
||||
$("#red-ui-view-zoom-zero").on("click", zoomZero);
|
||||
RED.popover.tooltip($("#red-ui-view-zoom-zero"),RED._('actions.zoom-reset'),'core:zoom-reset');
|
||||
$("#red-ui-view-zoom-in").on("click", function() { zoomIn(); });
|
||||
RED.popover.tooltip($("#red-ui-view-zoom-in"),RED._('actions.zoom-in'),'core:zoom-in');
|
||||
$("#red-ui-view-zoom-fit").on("click", zoomToFitAll);
|
||||
RED.popover.tooltip($("#red-ui-view-zoom-fit"),RED._('actions.zoom-fit'),'core:zoom-fit');
|
||||
// Legacy mouse wheel handler - disabled in favor of modern wheel event
|
||||
// chart.on("DOMMouseScroll mousewheel", function (evt) {
|
||||
// if ( evt.altKey || spacebarPressed ) {
|
||||
// evt.preventDefault();
|
||||
// evt.stopPropagation();
|
||||
// // Get cursor position relative to the chart
|
||||
// var offset = chart.offset();
|
||||
// var cursorPos = [
|
||||
// evt.originalEvent.pageX - offset.left,
|
||||
// evt.originalEvent.pageY - offset.top
|
||||
// ];
|
||||
// var move = -(evt.originalEvent.detail) || evt.originalEvent.wheelDelta;
|
||||
// if (move <= 0) { zoomOut(cursorPos); }
|
||||
// else { zoomIn(cursorPos); }
|
||||
// }
|
||||
// });
|
||||
|
||||
// Modern wheel event handler for better trackpad support (pinch-to-zoom) and momentum
|
||||
var momentumTimer = null;
|
||||
var trackpadGestureTimer = null;
|
||||
|
|
@ -824,7 +789,6 @@ RED.view = (function() {
|
|||
if (evt.ctrlKey || evt.altKey || spacebarPressed) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
|
||||
var currentTime = Date.now();
|
||||
var timeSinceLastEvent = currentTime - lastWheelEventTime;
|
||||
|
||||
|
|
@ -845,7 +809,6 @@ RED.view = (function() {
|
|||
var minZoom = calculateMinZoom();
|
||||
var newScale = Math.min(RED.view.zoomConstants.MAX_ZOOM,
|
||||
Math.max(minZoom, scaleFactor + scaleDelta));
|
||||
|
||||
// Session-based gesture tracking:
|
||||
// - If no active gesture OR gap > gestureEndThreshold, start new gesture
|
||||
// - If gap < wheelEventContinuityThreshold, continue current gesture
|
||||
|
|
@ -869,6 +832,10 @@ RED.view = (function() {
|
|||
var currentScrollPos = [chart.scrollLeft(), chart.scrollTop()];
|
||||
var focalPoint = RED.view.zoomAnimator.getGestureFocalPoint(currentScrollPos, scaleFactor);
|
||||
zoomView(newScale, focalPoint); // Direct call, no animation
|
||||
} else {
|
||||
// At a limit - force a refresh to ensure UI elements are correctly updated
|
||||
_redraw()
|
||||
RED.events.emit("view:navigate");
|
||||
}
|
||||
|
||||
// Update last event time for continuity tracking
|
||||
|
|
@ -913,6 +880,11 @@ RED.view = (function() {
|
|||
var currentScrollPos = [chart.scrollLeft(), chart.scrollTop()];
|
||||
var focalPoint = RED.view.zoomAnimator.getGestureFocalPoint(currentScrollPos, scaleFactor);
|
||||
zoomView(newScale, focalPoint);
|
||||
} else {
|
||||
// At a limit - force a refresh to ensure UI elements are correctly updated
|
||||
_redraw()
|
||||
RED.events.emit("view:navigate");
|
||||
|
||||
}
|
||||
|
||||
// Update last event time for continuity tracking
|
||||
|
|
@ -963,33 +935,6 @@ RED.view = (function() {
|
|||
}
|
||||
});
|
||||
|
||||
//add search to status-toolbar
|
||||
RED.statusBar.add({
|
||||
id: "view-search-tools",
|
||||
align: "left",
|
||||
hidden: false,
|
||||
element: $('<span class="button-group">'+
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-searchtools-search"><i class="fa fa-search"></i></button>' +
|
||||
'</span>' +
|
||||
'<span class="button-group red-ui-view-searchtools-counter">' +
|
||||
'<span class="red-ui-footer-button" id="red-ui-view-searchtools-counter-label">? of ?</span>' +
|
||||
'</span>' +
|
||||
'<span class="button-group">' +
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-searchtools-prev"><i class="fa fa-chevron-left"></i></button>' +
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-searchtools-next"><i class="fa fa-chevron-right"></i></button>' +
|
||||
'</span>' +
|
||||
'<span class="button-group">' +
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-searchtools-close"><i class="fa fa-close"></i></button>' +
|
||||
'</span>')
|
||||
})
|
||||
$("#red-ui-view-searchtools-search").on("click", searchFlows);
|
||||
RED.popover.tooltip($("#red-ui-view-searchtools-search"),RED._('actions.search-flows'),'core:search');
|
||||
$("#red-ui-view-searchtools-prev").on("click", searchPrev);
|
||||
RED.popover.tooltip($("#red-ui-view-searchtools-prev"),RED._('actions.search-prev'),'core:search-previous');
|
||||
$("#red-ui-view-searchtools-next").on("click", searchNext);
|
||||
RED.popover.tooltip($("#red-ui-view-searchtools-next"),RED._('actions.search-next'),'core:search-next');
|
||||
RED.popover.tooltip($("#red-ui-view-searchtools-close"),RED._('common.label.close'));
|
||||
|
||||
// Handle nodes dragged from the palette
|
||||
chart.droppable({
|
||||
accept:".red-ui-palette-node",
|
||||
|
|
@ -1237,6 +1182,55 @@ RED.view = (function() {
|
|||
RED.view.navigator.init();
|
||||
RED.view.tools.init();
|
||||
|
||||
RED.statusBar.add({
|
||||
id: "view-zoom-controls",
|
||||
align: "left",
|
||||
element: $('<span class="button-group">'+
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-zoom-out"><i class="fa fa-minus"></i></button>'+
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-zoom-zero"><i class="fa fa-circle-o"></i></button>'+
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-zoom-in"><i class="fa fa-plus"></i></button>'+
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-zoom-fit"><i class="fa fa-compress"></i></button>'+
|
||||
'</span>')
|
||||
})
|
||||
|
||||
$("#red-ui-view-zoom-out").on("click", function() { zoomOut(); });
|
||||
RED.popover.tooltip($("#red-ui-view-zoom-out"),RED._('actions.zoom-out'),'core:zoom-out');
|
||||
$("#red-ui-view-zoom-zero").on("click", zoomZero);
|
||||
RED.popover.tooltip($("#red-ui-view-zoom-zero"),RED._('actions.zoom-reset'),'core:zoom-reset');
|
||||
$("#red-ui-view-zoom-in").on("click", function() { zoomIn(); });
|
||||
RED.popover.tooltip($("#red-ui-view-zoom-in"),RED._('actions.zoom-in'),'core:zoom-in');
|
||||
$("#red-ui-view-zoom-fit").on("click", zoomToFitAll);
|
||||
RED.popover.tooltip($("#red-ui-view-zoom-fit"),RED._('actions.zoom-fit'),'core:zoom-fit');
|
||||
|
||||
//add search to status-toolbar
|
||||
RED.statusBar.add({
|
||||
id: "view-search-tools",
|
||||
align: "left",
|
||||
hidden: false,
|
||||
element: $('<span class="button-group">'+
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-searchtools-search"><i class="fa fa-search"></i></button>' +
|
||||
'</span>' +
|
||||
'<span class="button-group red-ui-view-searchtools-counter">' +
|
||||
'<span class="red-ui-footer-button" id="red-ui-view-searchtools-counter-label">? of ?</span>' +
|
||||
'</span>' +
|
||||
'<span class="button-group">' +
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-searchtools-prev"><i class="fa fa-chevron-left"></i></button>' +
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-searchtools-next"><i class="fa fa-chevron-right"></i></button>' +
|
||||
'</span>' +
|
||||
'<span class="button-group">' +
|
||||
'<button class="red-ui-footer-button" id="red-ui-view-searchtools-close"><i class="fa fa-close"></i></button>' +
|
||||
'</span>')
|
||||
})
|
||||
$("#red-ui-view-searchtools-search").on("click", searchFlows);
|
||||
RED.popover.tooltip($("#red-ui-view-searchtools-search"),RED._('actions.search-flows'),'core:search');
|
||||
$("#red-ui-view-searchtools-prev").on("click", searchPrev);
|
||||
RED.popover.tooltip($("#red-ui-view-searchtools-prev"),RED._('actions.search-prev'),'core:search-previous');
|
||||
$("#red-ui-view-searchtools-next").on("click", searchNext);
|
||||
RED.popover.tooltip($("#red-ui-view-searchtools-next"),RED._('actions.search-next'),'core:search-next');
|
||||
RED.popover.tooltip($("#red-ui-view-searchtools-close"),RED._('common.label.close'));
|
||||
|
||||
|
||||
|
||||
RED.view.annotations.register("red-ui-flow-node-docs",{
|
||||
type: "badge",
|
||||
class: "red-ui-flow-node-docs",
|
||||
|
|
@ -2960,6 +2954,8 @@ RED.view = (function() {
|
|||
}
|
||||
|
||||
animatedZoomView(Math.max(scaleFactor - RED.view.zoomConstants.ZOOM_STEP, minZoom), useFocalPoint, buttonZoomWorkspaceCenter);
|
||||
} else {
|
||||
// RED.events.emit("view:navigate"); // Ensure UI updates to reflect zoom limit reached
|
||||
}
|
||||
}
|
||||
function zoomZero() {
|
||||
|
|
@ -3063,6 +3059,7 @@ RED.view = (function() {
|
|||
onStep: function(values) {
|
||||
chart.scrollLeft(values.scrollLeft);
|
||||
chart.scrollTop(values.scrollTop);
|
||||
RED.events.emit("view:navigate");
|
||||
},
|
||||
onStart: function() {
|
||||
RED.events.emit("view:navigate");
|
||||
|
|
@ -3089,7 +3086,6 @@ RED.view = (function() {
|
|||
factor = 1
|
||||
}
|
||||
|
||||
console.log(factor)
|
||||
var screenSize = [chart.width(),chart.height()];
|
||||
var scrollPos = [chart.scrollLeft(),chart.scrollTop()];
|
||||
var oldScaleFactor = scaleFactor;
|
||||
|
|
@ -3144,6 +3140,7 @@ RED.view = (function() {
|
|||
// If we're already at the target, no need to animate
|
||||
// Use a more tolerant threshold to account for floating-point precision
|
||||
if (Math.abs(scaleFactor - targetFactor) < 0.01) {
|
||||
RED.events.emit("view:navigate");
|
||||
return;
|
||||
}
|
||||
// Make scale 1 'sticky'
|
||||
|
|
@ -3217,6 +3214,8 @@ RED.view = (function() {
|
|||
eventLayer.attr("transform", "scale(" + scaleFactor + ")");
|
||||
outer.attr("width", space_width * scaleFactor).attr("height", space_height * scaleFactor);
|
||||
RED.view.navigator.resize();
|
||||
_redraw()
|
||||
RED.events.emit("view:navigate");
|
||||
},
|
||||
onStart: function() {
|
||||
// Show minimap when zoom animation starts
|
||||
|
|
@ -3227,15 +3226,18 @@ RED.view = (function() {
|
|||
// Ensure scaleFactor is exactly the target to prevent precision issues
|
||||
scaleFactor = targetFactor;
|
||||
// Full redraw at the end to ensure everything is correct
|
||||
redraw();
|
||||
_redraw();
|
||||
if (RED.settings.get("editor.view.view-store-zoom")) {
|
||||
RED.settings.setLocal('zoom-level', targetFactor.toFixed(1));
|
||||
}
|
||||
RED.events.emit("view:navigate");
|
||||
},
|
||||
onCancel: function() {
|
||||
cancelInProgressAnimation = null;
|
||||
// Ensure scaleFactor is set to current target on cancel
|
||||
scaleFactor = targetFactor;
|
||||
_redraw();
|
||||
RED.events.emit("view:navigate");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -3287,6 +3289,7 @@ RED.view = (function() {
|
|||
// Apply new scroll position
|
||||
chart.scrollLeft(newScrollX);
|
||||
chart.scrollTop(newScrollY);
|
||||
RED.events.emit("view:navigate");
|
||||
|
||||
// Stop if velocity is too small
|
||||
if (Math.abs(scrollVelocity.x) < MIN_VELOCITY && Math.abs(scrollVelocity.y) < MIN_VELOCITY) {
|
||||
|
|
@ -7870,6 +7873,7 @@ RED.view = (function() {
|
|||
if (x !== undefined && y !== undefined) {
|
||||
chart.scrollLeft(chart.scrollLeft()+x);
|
||||
chart.scrollTop(chart.scrollTop()+y)
|
||||
RED.events.emit("view:navigate");
|
||||
} else {
|
||||
return [chart.scrollLeft(), chart.scrollTop()]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -497,17 +497,119 @@ RED.workspaces = (function() {
|
|||
$("#red-ui-workspace-footer").children().hide()
|
||||
}
|
||||
|
||||
const scrollbars = {}
|
||||
function updateScrollbars() {
|
||||
const scaleFactor = RED.view.scale();
|
||||
const chartWindowSize = [ $("#red-ui-workspace-chart").width(), $("#red-ui-workspace-chart").height()];
|
||||
const chartSize = [ $("#red-ui-workspace-scroll-spacer").width(), $("#red-ui-workspace-scroll-spacer").height()];
|
||||
const scrollPos = [$("#red-ui-workspace-chart").scrollLeft(), $("#red-ui-workspace-chart").scrollTop()];
|
||||
const scrollRatio = [scrollPos[0]/(chartSize[0] - chartWindowSize[0]), scrollPos[1]/(chartSize[1] - chartWindowSize[1]) ];
|
||||
const scrollbarSize = [scrollbars.h.bar.width(), scrollbars.v.bar.height()]
|
||||
// Set the height of the handles to be the same ratio of chartWindowSize to chartSize, with a minimum size to ensure they are always draggable
|
||||
|
||||
scrollbars.v.handle.height(Math.max(40, scrollbarSize[1] * chartWindowSize[1] / chartSize[1]))
|
||||
scrollbars.h.handle.width(Math.max(40, scrollbarSize[0] * chartWindowSize[0] / chartSize[0]))
|
||||
if (isNaN(scrollRatio[0])) {
|
||||
scrollbars.h.bar.hide()
|
||||
} else {
|
||||
scrollbars.h.bar.show()
|
||||
const sbhWidth = scrollbars.h.bar.width() - scrollbars.h.handle.width()
|
||||
scrollbars.h.handle.css({ left: sbhWidth * scrollRatio[0] })
|
||||
}
|
||||
if (isNaN(scrollRatio[1])) {
|
||||
scrollbars.v.bar.hide()
|
||||
} else {
|
||||
scrollbars.v.bar.show()
|
||||
const sbvHeight = scrollbars.v.bar.height() - scrollbars.v.handle.height()
|
||||
scrollbars.v.handle.css({ top: sbvHeight * scrollRatio[1] })
|
||||
}
|
||||
}
|
||||
|
||||
function setupScrollbar(scrollbar, direction) {
|
||||
// direction: 'h' | 'v'
|
||||
let isDragging = false;
|
||||
let dragStartPos = 0;
|
||||
let handleStartPos = 0;
|
||||
function cancelScroll () {
|
||||
isDragging = false;
|
||||
$(document).off('mousemove.red-ui-workspace-scrollbar');
|
||||
$(document).off('mouseup.red-ui-workspace-scrollbar');
|
||||
}
|
||||
// Update the following event handlers to also handle touch events
|
||||
scrollbar.handle.on('mousedown', function(evt) {
|
||||
isDragging = true;
|
||||
dragStartPos = (direction === 'h' ? evt.pageX : evt.pageY);
|
||||
handleStartPos = parseInt(scrollbar.handle.css(direction === 'h' ? 'left' : 'top')) || 0;
|
||||
evt.preventDefault();
|
||||
$(document).on('mousemove.red-ui-workspace-scrollbar', function(evt) {
|
||||
if (isDragging) {
|
||||
const delta = (direction === 'h' ? evt.pageX : evt.pageY) - dragStartPos;
|
||||
const newHandlePos = handleStartPos + delta;
|
||||
const barSize = (direction === 'h' ? scrollbar.bar.width() : scrollbar.bar.height()) - (direction === 'h' ? scrollbar.handle.width() : scrollbar.handle.height());
|
||||
const clampedHandlePos = Math.max(0, Math.min(newHandlePos, barSize));
|
||||
const scrollRatio = clampedHandlePos / barSize;
|
||||
const chartWindowSize = [ $("#red-ui-workspace-chart").width(), $("#red-ui-workspace-chart").height()];
|
||||
const chartSize = [ $("#red-ui-workspace-scroll-spacer").width(), $("#red-ui-workspace-scroll-spacer").height()];
|
||||
if (direction === 'h') {
|
||||
const newScrollLeft = scrollRatio * (chartSize[0] - chartWindowSize[0]);
|
||||
$("#red-ui-workspace-chart").scrollLeft(newScrollLeft);
|
||||
} else {
|
||||
const newScrollTop = scrollRatio * (chartSize[1] - chartWindowSize[1]);
|
||||
$("#red-ui-workspace-chart").scrollTop(newScrollTop);
|
||||
}
|
||||
updateScrollbars()
|
||||
} else {
|
||||
$(document).off('mousemove.red-ui-workspace-scrollbar');
|
||||
}
|
||||
})
|
||||
$(document).on('mouseup.red-ui-workspace-scrollbar', function(evt) {
|
||||
cancelScroll()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
$('<ul id="red-ui-workspace-tabs"></ul>').appendTo("#red-ui-workspace");
|
||||
$('<div id="red-ui-workspace-tabs-shade" class="hide"></div>').appendTo("#red-ui-workspace");
|
||||
$('<ul id="red-ui-workspace-tabs"></ul>').appendTo("#red-ui-header-tabs");
|
||||
$('<div id="red-ui-workspace-tabs-shade" class="hide"></div>').appendTo("#red-ui-header-tabs");
|
||||
$('<div id="red-ui-workspace-chart" tabindex="1"></div>').appendTo("#red-ui-workspace");
|
||||
$('<div id="red-ui-workspace-toolbar"></div>').appendTo("#red-ui-workspace");
|
||||
$('<div id="red-ui-workspace-footer" class="red-ui-component-footer"></div>').appendTo("#red-ui-workspace");
|
||||
$('<div id="red-ui-workspace-footer" class="red-ui-component-footer"></div>').insertAfter("#red-ui-workspace");
|
||||
|
||||
scrollbars.v = { bar: $('<div id="red-ui-workspace-scroll-v" class="red-ui-workspace-scrollbar"><div class="red-ui-workspace-scrollbar-handle"><div class="red-ui-workspace-scrollbar-handle-target"></div></div></div>').appendTo("#red-ui-workspace") }
|
||||
scrollbars.v.handle = scrollbars.v.bar.children().first();
|
||||
setupScrollbar(scrollbars.v, 'v')
|
||||
scrollbars.h = { bar: $('<div id="red-ui-workspace-scroll-h" class="red-ui-workspace-scrollbar"><div class="red-ui-workspace-scrollbar-handle"><div class="red-ui-workspace-scrollbar-handle-target"></div></div></div>').appendTo("#red-ui-workspace") }
|
||||
scrollbars.h.handle = scrollbars.h.bar.children().first();
|
||||
setupScrollbar(scrollbars.h, 'h')
|
||||
|
||||
$('<div id="red-ui-editor-shade" class="hide"></div>').appendTo("#red-ui-workspace");
|
||||
|
||||
|
||||
createWorkspaceTabs();
|
||||
RED.events.on("sidebar:resize",workspace_tabs.resize);
|
||||
RED.events.on("view:navigate", function () {
|
||||
updateScrollbars()
|
||||
})
|
||||
RED.events.on("sidebar:resize",function () {
|
||||
workspace_tabs.resize();
|
||||
let sidebarWidth = $("#red-ui-sidebar-container").width()
|
||||
const workspaceTargetWidth = $("#red-ui-workspace").width() - sidebarWidth
|
||||
// $("#red-ui-workspace-toolbar").width(workspaceTargetWidth)
|
||||
// $("#red-ui-workspace-footer").width(workspaceTargetWidth)
|
||||
$("#red-ui-workspace-scroll-v").css({ right: sidebarWidth + 2})
|
||||
$("#red-ui-workspace-scroll-h").css({ width: workspaceTargetWidth - 15 })
|
||||
|
||||
const paletteWidth = $("#red-ui-sidebar-left").width()
|
||||
$("#red-ui-header-logo").width(paletteWidth - 5)
|
||||
|
||||
// const workspacePosition = $("#red-ui-workspace").position()
|
||||
// $("#red-ui-header-tabs").css({ left: workspacePosition.left, width: workspaceTargetWidth })
|
||||
updateScrollbars()
|
||||
});
|
||||
|
||||
RED.events.on("workspace:change", function(event) {
|
||||
setTimeout(() => {
|
||||
updateScrollbars()
|
||||
}, 100)
|
||||
});
|
||||
|
||||
RED.events.on("workspace:clear", () => {
|
||||
// Reset the index used to generate new flow names
|
||||
|
|
@ -534,7 +636,8 @@ RED.workspaces = (function() {
|
|||
});
|
||||
|
||||
$(window).on("resize", function() {
|
||||
workspace_tabs.resize();
|
||||
// workspace_tabs.resize();
|
||||
updateScrollbars()
|
||||
});
|
||||
if (RED.settings.theme("menu.menu-item-workspace-add", true)) {
|
||||
RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)});
|
||||
|
|
|
|||
|
|
@ -248,6 +248,8 @@ $clipboard-textarea-background: #F3E7E7;
|
|||
|
||||
$header-background: $primary-background;
|
||||
$header-button-border: $primary-border-color;
|
||||
$header-button-background: $header-background;
|
||||
$header-button-background-hover: #ddd;
|
||||
$header-button-background-active: $workspace-button-background-active;
|
||||
$header-accent: $primary-background;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@
|
|||
position:absolute;
|
||||
margin: 8px 0 8px 7px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
//min-width: 500px;
|
||||
bottom: 34px;
|
||||
width: auto;
|
||||
right: -1000px;
|
||||
box-sizing: border-box;
|
||||
|
|
@ -50,7 +49,7 @@
|
|||
background: var(--red-ui-secondary-background);
|
||||
border: 1px solid var(--red-ui-primary-border-color);
|
||||
overflow: hidden;
|
||||
box-shadow: -2px 0 6px var(--red-ui-shadow);
|
||||
// box-shadow: -2px 0 6px var(--red-ui-shadow);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,11 +34,15 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-top: 6px;
|
||||
|
||||
span.red-ui-header-logo {
|
||||
float: left;
|
||||
#red-ui-header-logo {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 8px;
|
||||
min-width: 170px;
|
||||
}
|
||||
span.red-ui-header-logo {
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
|
||||
|
|
@ -63,12 +67,15 @@
|
|||
}
|
||||
|
||||
.red-ui-header-toolbar {
|
||||
display: flex;
|
||||
flex: 1 0 auto;
|
||||
&:not(.hide) {
|
||||
display: flex;
|
||||
}
|
||||
align-items: stretch;
|
||||
padding: 0;
|
||||
margin: 0 10px 0 0;
|
||||
margin: 0 10px 0 20px;
|
||||
list-style: none;
|
||||
gap: 15px;
|
||||
gap: 10px;
|
||||
|
||||
> li {
|
||||
display: inline-flex;
|
||||
|
|
@ -80,26 +87,27 @@
|
|||
}
|
||||
|
||||
.button {
|
||||
height: 24px;
|
||||
height: 30px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 24px;
|
||||
min-width: 32px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
padding: 0px;
|
||||
text-decoration: none;
|
||||
color: var(--red-ui-header-menu-color);
|
||||
margin: auto 0;
|
||||
vertical-align: middle;
|
||||
mask-size: contain;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:active, &.active {
|
||||
background: var(--red-ui-header-button-background-active);
|
||||
}
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
&:hover {
|
||||
background: var(--red-ui-header-button-background-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.button-group {
|
||||
|
|
@ -109,7 +117,6 @@
|
|||
& > a {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
float: left;
|
||||
line-height: 22px;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
|
|
@ -303,11 +310,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.red-ui-user-profile {
|
||||
#red-ui-header-button-user {
|
||||
background-color: var(--red-ui-header-background);
|
||||
border: 1px solid var(--red-ui-header-button-border);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.red-ui-user-profile {
|
||||
overflow: hidden;
|
||||
padding: 3px;
|
||||
background-position: center center;
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@
|
|||
vertical-align: middle;
|
||||
}
|
||||
.button-group:not(:last-child) {
|
||||
margin-right: 10px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -263,7 +263,6 @@
|
|||
width: 24px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin-top: 1px;
|
||||
// width: 30px;
|
||||
// height: 25px;
|
||||
border-radius: 3px;
|
||||
|
|
|
|||
|
|
@ -16,16 +16,20 @@
|
|||
* limitations under the License.
|
||||
**/
|
||||
|
||||
#red-ui-sidebar-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.red-ui-sidebar {
|
||||
position: relative;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
width: 315px;
|
||||
margin: 4px 0;
|
||||
@include mixins.component-border;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
background: var(--red-ui-secondary-background);
|
||||
margin: 4px 0 40px 0;
|
||||
box-sizing: border-box;
|
||||
z-index: 12;
|
||||
display: flex;
|
||||
|
|
@ -34,12 +38,13 @@
|
|||
}
|
||||
.red-ui-sidebar-left {
|
||||
background: var(--red-ui-primary-background);
|
||||
margin: 0;
|
||||
margin-top: 0px;
|
||||
margin-left: 5px;
|
||||
border: none;
|
||||
z-index: 10;
|
||||
}
|
||||
.red-ui-sidebar-right {
|
||||
margin-left: 0;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.red-ui-sidebar-footer {
|
||||
|
|
@ -51,27 +56,31 @@
|
|||
}
|
||||
|
||||
.red-ui-sidebar-section {
|
||||
margin: 4px;
|
||||
margin: 8px 4px 0 4px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 80px;
|
||||
background: rgba(0,0,255,0.2);
|
||||
// background: rgba(0,0,255,0.2);
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--red-ui-secondary-border-color);
|
||||
border: 1px solid var(--red-ui-primary-border-color);
|
||||
overflow: hidden;
|
||||
&.red-ui-sidebar-section-top { margin-top: 4px; }
|
||||
&.red-ui-sidebar-section-bottom {
|
||||
&:first-child {
|
||||
margin-top: 4px;
|
||||
}
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
}
|
||||
.red-ui-sidebar-left .red-ui-sidebar-section {
|
||||
margin-left: 0;
|
||||
border-color: var(--red-ui-primary-border-color);
|
||||
&.red-ui-sidebar-section-top { margin-top: 0; }
|
||||
}
|
||||
.red-ui-sidebar-right .red-ui-sidebar-section {
|
||||
margin-right: 0
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -99,11 +108,10 @@
|
|||
|
||||
.red-ui-sidebar-separator-handle {
|
||||
position: absolute;
|
||||
// background: rgba(255,140,0,0.2);
|
||||
top: 0;
|
||||
left: -6px;
|
||||
width: 12px;
|
||||
height: 100%;
|
||||
height: calc(100% - 40px);;
|
||||
z-index: 20;
|
||||
}
|
||||
}
|
||||
|
|
@ -127,31 +135,24 @@
|
|||
}
|
||||
|
||||
.red-ui-sidebar-tab-bar {
|
||||
background-color: var(--red-ui-secondary-background);
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
flex: 0 0 auto;
|
||||
align-items: center;
|
||||
margin: 4px;
|
||||
@include mixins.component-border;
|
||||
flex-wrap: nowrap;
|
||||
margin: 0;
|
||||
z-index: 12;
|
||||
overflow: hidden;
|
||||
// border: 1px solid var(--red-ui-primary-border-color);
|
||||
// background: rgba(243, 160, 204, 0.617);
|
||||
|
||||
&.red-ui-sidebar-left {
|
||||
z-index: 10;
|
||||
border: none;
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
background: var(--red-ui-primary-background);
|
||||
margin-left: 5px;
|
||||
background: none;
|
||||
}
|
||||
&.red-ui-sidebar-right {
|
||||
border-top-right-radius: 8px;
|
||||
border-bottom-right-radius: 8px;
|
||||
margin-left: 0;
|
||||
// Account for the RH sidebar having an extra top margin
|
||||
padding-top: 4px;
|
||||
border-left: none;
|
||||
border-bottom: none;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
button {
|
||||
|
|
@ -162,17 +163,21 @@
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
&:not(.selected):not(:hover) {
|
||||
border: none;
|
||||
i {
|
||||
opacity: 0.7;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
i {
|
||||
font-size: 13px;
|
||||
}
|
||||
border-color: var(--red-ui-secondary-border-color);
|
||||
&.selected {
|
||||
background-color: var(--red-ui-secondary-color);
|
||||
border-color: var(--red-ui-primary-border-color);
|
||||
}
|
||||
}
|
||||
.red-ui-sidebar-tab-bar-button-placeholder {
|
||||
border: 1px dashed var(--red-ui-form-input-border-color) !important;
|
||||
|
|
@ -180,33 +185,55 @@
|
|||
|
||||
.red-ui-sidebar-tab-bar-buttons {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
// background-color: var(--red-ui-primary-background);
|
||||
// background: rgba(255, 0, 0, 0.1);
|
||||
padding: 6px;
|
||||
// background: rgba(233, 255, 91, 0.555);
|
||||
|
||||
height: 28px;
|
||||
padding: 0 6px;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-grow: 1;
|
||||
gap: 8px;
|
||||
flex-grow: 0;
|
||||
// height: 50%;
|
||||
&:first-child {
|
||||
// background: rgba(255,0,0,0.1);
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
&:last-child {
|
||||
// background: rgba(255,255,0,0.1);
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
// &:first-child {
|
||||
// // background: rgba(255,0,0,0.1);
|
||||
// flex-grow: 0;
|
||||
// flex-shrink: 0;
|
||||
// }
|
||||
// &:last-child {
|
||||
// // background: rgba(255,255,0,0.1);
|
||||
// flex-grow: 1;
|
||||
// flex-shrink: 1;
|
||||
// }
|
||||
}
|
||||
.red-ui-sidebar-tab-bar-buttons.red-ui-sidebar-tab-bar-empty {
|
||||
display: none;
|
||||
// background: rgba(255,0,0,0.3);
|
||||
}
|
||||
&.red-ui-sidebar-dragging-tab .red-ui-sidebar-tab-bar-empty {
|
||||
display: flex;
|
||||
}
|
||||
&.red-ui-sidebar-dragging-tab .red-ui-sidebar-tab-bar-buttons:last-child {
|
||||
border-top: 2px dashed var(--red-ui-form-input-border-color);
|
||||
margin-top: -2px;
|
||||
border-left: 2px dashed var(--red-ui-secondary-border-color);
|
||||
// margin-left: -2px;
|
||||
width: 42px;
|
||||
height: 28px;
|
||||
}
|
||||
.red-ui-sidebar-tab-bar-buttons:last-child {
|
||||
min-width: 28px;
|
||||
border-left: 2px solid var(--red-ui-secondary-border-color);
|
||||
}
|
||||
.red-ui-sidebar-right & {
|
||||
justify-items: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.red-ui-sidebar-right .red-ui-sidebar-tab-bar-buttons:first-child {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
|
||||
.red-ui-sidebar .button {
|
||||
@include mixins.workspace-button;
|
||||
line-height: 18px;
|
||||
|
|
@ -215,14 +242,27 @@
|
|||
padding: 2px 8px;
|
||||
}
|
||||
|
||||
.red-ui-sidebar-banner { /* Currently unused... */
|
||||
background: var(--red-ui-primary-background);
|
||||
color: var(--red-ui-primary-text-color);
|
||||
font-size: 8px;
|
||||
padding: 0 3px;
|
||||
text-align: right;
|
||||
user-select: none;
|
||||
cursor: grab;
|
||||
}
|
||||
.sidebar-header, /* Deprecated -> red-ui-sidebar-header */
|
||||
.red-ui-sidebar-header {
|
||||
font-size: 13px;
|
||||
color: var(--red-ui-primary-text-color);
|
||||
text-align: right;
|
||||
padding: 8px 10px;
|
||||
padding: 4px;
|
||||
background: var(--red-ui-primary-background);
|
||||
border-bottom: 1px solid var(--red-ui-secondary-border-color);
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
/* Deprecated -> red-ui-footer-button */
|
||||
|
|
@ -239,9 +279,9 @@ button.sidebar-header-button, /* Deprecated -> red-ui-sidebar-header-button */
|
|||
a.red-ui-sidebar-header-button,
|
||||
button.red-ui-sidebar-header-button {
|
||||
@include mixins.workspace-button;
|
||||
font-size: 13px;
|
||||
line-height: 13px;
|
||||
padding: 5px 8px;
|
||||
font-size: 11px;
|
||||
line-height: 11px;
|
||||
padding: 3px 5px;
|
||||
&.toggle {
|
||||
@include mixins.workspace-button-toggle;
|
||||
}
|
||||
|
|
@ -252,9 +292,9 @@ button.sidebar-header-button-toggle, /* Deprecated -> red-ui-sidebar-header-butt
|
|||
a.red-ui-sidebar-header-button-toggle,
|
||||
button.red-ui-sidebar-header-button-toggle {
|
||||
@include mixins.workspace-button-toggle;
|
||||
font-size: 13px;
|
||||
line-height: 13px;
|
||||
padding: 5px 8px;
|
||||
font-size: 11px;
|
||||
line-height: 11px;
|
||||
padding: 3px 5px;
|
||||
}
|
||||
|
||||
.sidebar-header-button:not(:first-child), /* Deprecated -> red-ui-sidebar-header-button */
|
||||
|
|
|
|||
|
|
@ -14,4 +14,4 @@
|
|||
* limitations under the License.
|
||||
**/
|
||||
|
||||
$header-height: 36px;
|
||||
$header-height: 40px;
|
||||
|
|
@ -23,27 +23,17 @@
|
|||
.red-ui-sidebar-info hr {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.red-ui-info-header {
|
||||
padding-left: 9px;
|
||||
line-height: 21px;
|
||||
cursor: default;
|
||||
border-bottom: 1px solid var(--red-ui-secondary-border-color);
|
||||
> * {
|
||||
vertical-align: middle
|
||||
}
|
||||
> span {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
}
|
||||
|
||||
table.red-ui-info-table {
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
margin: 0 0 10px;
|
||||
width: 100%;
|
||||
}
|
||||
table.red-ui-info-table tr:not(.blank) {
|
||||
border-top: 1px solid var(--red-ui-secondary-border-color);
|
||||
&:not(:first-child) {
|
||||
border-top: 1px solid var(--red-ui-secondary-border-color);
|
||||
}
|
||||
line-height: 23px;
|
||||
border-bottom: 1px solid var(--red-ui-secondary-border-color);
|
||||
}
|
||||
.red-ui-help-property-expand {
|
||||
|
|
@ -360,7 +350,7 @@ div.red-ui-info-table {
|
|||
.red-ui-info-outline-item {
|
||||
display: inline-flex;
|
||||
padding: 0;
|
||||
font-size: 13px;
|
||||
font-size: 12px;
|
||||
border: none;
|
||||
&:not(.red-ui-node-list-item) .red-ui-palette-icon-fa {
|
||||
position: relative;
|
||||
|
|
|
|||
|
|
@ -230,7 +230,6 @@
|
|||
left: 0;
|
||||
right: 0;
|
||||
opacity: 0.4;
|
||||
background: red;
|
||||
}
|
||||
}
|
||||
.red-ui-tab-button {
|
||||
|
|
@ -284,9 +283,8 @@
|
|||
width: 21px;
|
||||
top: 0;
|
||||
a {
|
||||
height: 35px;
|
||||
// height: 35px;
|
||||
width: 21px;
|
||||
display: block;
|
||||
color: var(--red-ui-workspace-button-color);
|
||||
font-size: 22px;
|
||||
text-align: center;
|
||||
|
|
@ -295,7 +293,6 @@
|
|||
border-right: none;
|
||||
border-top: none;
|
||||
border-bottom: 1px solid var(--red-ui-primary-border-color);
|
||||
line-height: 34px;
|
||||
}
|
||||
}
|
||||
.red-ui-tab-scroll-left {
|
||||
|
|
@ -435,19 +432,126 @@ i.red-ui-tab-icon {
|
|||
}
|
||||
}
|
||||
|
||||
ul#red-ui-workspace-tabs {
|
||||
border-color: var(--red-ui-secondary-border-color);
|
||||
li {
|
||||
border-color: var(--red-ui-secondary-border-color);
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
#red-ui-header-tabs {
|
||||
flex: 1 1 100%;
|
||||
border-right: 1px solid var(--red-ui-secondary-border-color);
|
||||
padding-right: 5px;
|
||||
|
||||
.red-ui-tabs {
|
||||
background: var(--red-ui-header-background);
|
||||
border: none;
|
||||
display: flex;
|
||||
padding: 0;
|
||||
.red-ui-tabs-scroll-container {
|
||||
min-width:0;
|
||||
width: 0;
|
||||
flex: 1 1 0;
|
||||
}
|
||||
.red-ui-tab-button {
|
||||
position: static;
|
||||
background: var(--red-ui-header-background);
|
||||
border: var(--red-ui-header-button-border);
|
||||
a {
|
||||
background: var(--red-ui-header-background);
|
||||
border: var(--red-ui-header-button-border);
|
||||
&:hover {
|
||||
background: var(--red-ui-header-button-background-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
.red-ui-tab-button.red-ui-tab-scroll {
|
||||
background: none;
|
||||
border: none;
|
||||
z-index:10;
|
||||
border-radius: 0;
|
||||
}
|
||||
.red-ui-tab-button.red-ui-tab-scroll a {
|
||||
border: none;
|
||||
background: none;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 8px rgba(0,0,0,0.3);
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.red-ui-tab-button.red-ui-tab-scroll.red-ui-tab-scroll-left a {
|
||||
border: none;
|
||||
clip-path: inset(0 -8px 0 0);
|
||||
}
|
||||
.red-ui-tab-button.red-ui-tab-scroll.red-ui-tab-scroll-right a {
|
||||
border: none;
|
||||
clip-path: inset(0 0 0 -8px);
|
||||
}
|
||||
}
|
||||
ul {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: none;
|
||||
gap: 2px;
|
||||
|
||||
li {
|
||||
min-width: 60px;
|
||||
max-width: 150px;
|
||||
flex: 1 1 100%;
|
||||
border-color: transparent;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
|
||||
a.red-ui-tab-label {
|
||||
padding: 0 6px;
|
||||
text-align: center;
|
||||
width: auto;
|
||||
|
||||
i.red-ui-tab-icon:not(.fa) {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.active) .red-ui-tabs-fade {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:not(.active) {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
&:not(:first-child):not(.active) {
|
||||
box-shadow: -1px 0 0 rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
&:not(:first-child):not(.active):hover,
|
||||
&.active + li:not(:first-child),
|
||||
&:hover + li:not(:first-child):not(.active) {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--red-ui-secondary-background);
|
||||
box-shadow: 0 1px 4px rgba(0,0,0,0.15);
|
||||
border-color: var(--red-ui-primary-border-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&:not(.active):hover::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0 0 0 1px;
|
||||
background: rgba(0,0,0,0.06);
|
||||
border-radius: 4px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:not(.active) a:hover {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#red-ui-workspace > .red-ui-tabs > .red-ui-tab-button {
|
||||
border-color: var(--red-ui-secondary-border-color);
|
||||
#red-ui-header-tabs > .red-ui-tabs > .red-ui-tab-button {
|
||||
border-color: var(--red-ui-header-button-border);
|
||||
}
|
||||
#red-ui-workspace > .red-ui-tabs > .red-ui-tab-scroll a {
|
||||
border-color: var(--red-ui-secondary-border-color);
|
||||
border-radius: 0;
|
||||
#red-ui-header-tabs > .red-ui-tabs > .red-ui-tab-scroll a {
|
||||
border-color: var(--red-ui-header-button-border);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -249,7 +249,10 @@
|
|||
|
||||
--red-ui-header-background: #{colors.$header-background};
|
||||
--red-ui-header-accent: #{colors.$header-accent};
|
||||
--red-ui-header-button-background: #{colors.$header-background};
|
||||
--red-ui-header-button-background-hover: #{colors.$header-button-background-hover};
|
||||
--red-ui-header-button-background-active: #{colors.$header-button-background-active};
|
||||
|
||||
--red-ui-header-button-border: #{colors.$header-button-border};
|
||||
--red-ui-header-menu-color: #{colors.$header-menu-color};
|
||||
--red-ui-header-menu-color-disabled: #{colors.$header-menu-color-disabled};
|
||||
|
|
|
|||
|
|
@ -20,37 +20,37 @@
|
|||
margin: 0;
|
||||
overflow: hidden;
|
||||
@include mixins.component-border;
|
||||
border-top-left-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
border-top-left-radius: 6px;
|
||||
border-right: none;
|
||||
margin: 4px 0 4px;
|
||||
border-bottom: none;
|
||||
transition: left 0.1s ease-in-out;
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
.red-ui-workspace-toolbar-active {
|
||||
top: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
#red-ui-workspace-chart {
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
bottom:0;
|
||||
top: 35px;
|
||||
left:0px;
|
||||
right:0px;
|
||||
box-sizing:border-box;
|
||||
transition: right 0.2s ease;
|
||||
touch-action: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-right: 1px solid var(--red-ui-secondary-border-color);
|
||||
// border-top-right-radius: px;
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
bottom:0;
|
||||
top: 0px;
|
||||
left:0px;
|
||||
right:0px;
|
||||
box-sizing:border-box;
|
||||
transition: right 0.2s ease;
|
||||
touch-action: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
// // Hide scrollbars
|
||||
// scrollbar-width: none; /* Firefox */
|
||||
// -ms-overflow-style: none; /* Internet Explorer 10+ */
|
||||
// &::-webkit-scrollbar { /* WebKit */
|
||||
// width: 0;
|
||||
// height: 0;
|
||||
// }
|
||||
// Hide scrollbars
|
||||
scrollbar-width: none; /* Firefox */
|
||||
-ms-overflow-style: none; /* Internet Explorer 10+ */
|
||||
&::-webkit-scrollbar { /* WebKit */
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
// Reset SVG default margins
|
||||
> svg {
|
||||
|
|
@ -88,9 +88,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
#red-ui-workspace-tabs:not(.red-ui-workspace-focussed) {
|
||||
opacity:0.8;
|
||||
}
|
||||
// #red-ui-workspace-tabs:not(.red-ui-workspace-focussed) {
|
||||
// opacity:0.8;
|
||||
// }
|
||||
.red-ui-workspace-disabled-icon {
|
||||
display: none;
|
||||
}
|
||||
|
|
@ -128,18 +128,6 @@
|
|||
}
|
||||
.red-ui-workspace-locked {
|
||||
&.red-ui-tab {
|
||||
// border-top-style: dashed;
|
||||
// border-left-style: dashed;
|
||||
// border-right-style: dashed;
|
||||
|
||||
// a {
|
||||
// font-style: italic;
|
||||
// color: var(--red-ui-tab-text-color-disabled-inactive) !important;
|
||||
// }
|
||||
// &.active a {
|
||||
// font-weight: normal;
|
||||
// color: var(--red-ui-tab-text-color-disabled-active) !important;
|
||||
// }
|
||||
.red-ui-workspace-locked-icon {
|
||||
display: inline;
|
||||
}
|
||||
|
|
@ -149,7 +137,7 @@
|
|||
#red-ui-navigator-canvas {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right:0;
|
||||
left:0;
|
||||
z-index: 101;
|
||||
border: 1px solid var(--red-ui-primary-border-color);
|
||||
background: var(--red-ui-view-navigator-background);
|
||||
|
|
@ -157,6 +145,10 @@
|
|||
border-radius: 4px;
|
||||
}
|
||||
|
||||
#view-zoom-controls .button-group button.red-ui-footer-button:not(:last-child) {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.red-ui-navigator-container {
|
||||
transition: opacity 0.3s ease;
|
||||
opacity: 0;
|
||||
|
|
@ -176,11 +168,17 @@
|
|||
opacity: 0.6;
|
||||
}
|
||||
#red-ui-workspace-footer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
border: none;
|
||||
background: none;
|
||||
bottom: 14px;
|
||||
right: 12px;
|
||||
bottom: 8px;
|
||||
right: 0;
|
||||
left: 0;
|
||||
padding: 0;
|
||||
// background: rgba(230,230,255,0.8);
|
||||
}
|
||||
.red-ui-component-footer {
|
||||
@include mixins.component-footer;
|
||||
|
|
@ -210,28 +208,42 @@ a.red-ui-footer-button-toggle,
|
|||
button.red-ui-footer-button-toggle {
|
||||
@include mixins.component-footer-button-toggle;
|
||||
}
|
||||
#red-ui-statusbar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
// background: rgba(62, 236, 53, 0.8);
|
||||
flex: 1 1 100%;
|
||||
height: 100%;
|
||||
padding-left: 5px;
|
||||
|
||||
}
|
||||
.red-ui-statusbar-widget {
|
||||
line-height: 1em;
|
||||
margin: 0 2px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 100%;
|
||||
line-height: 20px;
|
||||
& .red-ui-footer-button,
|
||||
& .red-ui-footer-button-toggle {
|
||||
min-width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.red-ui-statusbar-bucket {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.red-ui-statusbar-bucket-left {
|
||||
left: 6px;
|
||||
flex: 0 0 auto;
|
||||
.red-ui-statusbar-widget:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
.red-ui-statusbar-bucket-right {
|
||||
right: 6px;
|
||||
.red-ui-statusbar-widget:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
|
@ -277,3 +289,58 @@ button.red-ui-footer-button-toggle {
|
|||
font-size: 13px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
:root {
|
||||
--red-ui-scrollbar-width: 12px;
|
||||
--red-ui-scrollbar-handle-size: 40px;
|
||||
--red-ui-scrollbar-handle-background: rgb(200, 200, 200);
|
||||
}
|
||||
|
||||
.red-ui-workspace-scrollbar {
|
||||
position: absolute;
|
||||
// background: rgba(223, 236, 230, 0.8);
|
||||
}
|
||||
.red-ui-workspace-scrollbar-handle {
|
||||
position: absolute;
|
||||
background: var(--red-ui-scrollbar-handle-background);
|
||||
opacity: 0.7;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid rgba(255,255,255,1);
|
||||
cursor: pointer;
|
||||
overflow: visible;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.red-ui-workspace-scrollbar-handle-target {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
left: -5px;
|
||||
right: -5px;
|
||||
bottom: -5px;
|
||||
}
|
||||
}
|
||||
#red-ui-workspace-scroll-v {
|
||||
top: 2px;
|
||||
bottom: 46px;
|
||||
right: 0;
|
||||
width: var(--red-ui-scrollbar-width);
|
||||
.red-ui-workspace-scrollbar-handle {
|
||||
top: 0;
|
||||
left: 2px;
|
||||
width: 8px;
|
||||
height: var(--red-ui-scrollbar-handle-size);
|
||||
}
|
||||
}
|
||||
#red-ui-workspace-scroll-h {
|
||||
left: 2px;
|
||||
right: 0;
|
||||
bottom: 36px;
|
||||
height: var(--red-ui-scrollbar-width);
|
||||
.red-ui-workspace-scrollbar-handle {
|
||||
left: 0;
|
||||
top: 2px;
|
||||
height: 8px;
|
||||
width: var(--red-ui-scrollbar-handle-size);
|
||||
}
|
||||
// background: var(--red-ui-scrollbar-background);
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
position: absolute;
|
||||
top: 35px;
|
||||
top: 0;
|
||||
left:0;
|
||||
right: 0;
|
||||
padding: 7px;
|
||||
|
|
@ -53,6 +53,15 @@
|
|||
.button-group {
|
||||
@include mixins.disable-selection;
|
||||
|
||||
.button:not(:first-child) {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
.button:not(:last-child) {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.button:first-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,11 +45,11 @@ RED.debug = (function() {
|
|||
'<a id="red-ui-sidebar-debug-pause" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-pause"></i></a>'+
|
||||
'</span>'+
|
||||
'<span class="button-group">'+
|
||||
'<a id="red-ui-sidebar-debug-filter" style="padding-right: 5px" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-filter"></i> <span></span> <i style="padding-left: 5px;" class="fa fa-caret-down"></i></a>'+
|
||||
'<a id="red-ui-sidebar-debug-filter" style="padding-right: 3px" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-filter"></i> <span></span> <i style="padding-left: 5px;" class="fa fa-caret-down"></i></a>'+
|
||||
'</span>'+
|
||||
'<span class="button-group">'+
|
||||
'<a id="red-ui-sidebar-debug-clear" style="border-right: none; padding-right: 6px" class="red-ui-sidebar-header-button" href="#" data-clear-type="all"><i class="fa fa-trash"></i> <span>all</span></a>' +
|
||||
'<a id="red-ui-sidebar-debug-clear-opts" style="padding: 5px; border-left: none;" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-caret-down"></i></a>'+
|
||||
'<a id="red-ui-sidebar-debug-clear" style="border-right: none; padding-right: 2px" class="red-ui-sidebar-header-button" href="#" data-clear-type="all"><i class="fa fa-trash"></i> <span>all</span></a>' +
|
||||
'<a id="red-ui-sidebar-debug-clear-opts" style="padding: 3px; border-left: none;" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-caret-down"></i></a>'+
|
||||
'</span></div>').appendTo(content);
|
||||
|
||||
var footerToolbar = $('<div>'+
|
||||
|
|
|
|||
Loading…
Reference in New Issue