Merge pull request #5576 from Ultimaker/CURA-6435_new_style_add_machine

CURA-6435 New style add machine dialog
This commit is contained in:
Lipu Fei 2019-04-18 08:41:47 +02:00 committed by GitHub
commit 35b6ece3cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 160 additions and 18 deletions

1
.gitignore vendored
View File

@ -71,3 +71,4 @@ run.sh
.scannerwork/ .scannerwork/
CuraEngine CuraEngine
/.coverage

View File

@ -59,6 +59,10 @@ class WelcomePagesModel(ListModel):
# Store all the previous page indices so it can go back. # Store all the previous page indices so it can go back.
self._previous_page_indices_stack = deque() # type: deque self._previous_page_indices_stack = deque() # type: deque
# If the welcome flow should be shown. It can show the complete flow or just the changelog depending on the
# specific case. See initialize() for how this variable is set.
self._should_show_welcome_flow = False
allFinished = pyqtSignal() # emitted when all steps have been finished allFinished = pyqtSignal() # emitted when all steps have been finished
currentPageIndexChanged = pyqtSignal() currentPageIndexChanged = pyqtSignal()
@ -174,6 +178,12 @@ class WelcomePagesModel(ListModel):
self.currentPageIndexChanged.emit() self.currentPageIndexChanged.emit()
shouldShowWelcomeFlowChanged = pyqtSignal()
@pyqtProperty(bool, notify = shouldShowWelcomeFlowChanged)
def shouldShowWelcomeFlow(self) -> bool:
return self._should_show_welcome_flow
# Gets the page index with the given page ID. If the page ID doesn't exist, returns None. # Gets the page index with the given page ID. If the page ID doesn't exist, returns None.
def getPageIndexById(self, page_id: str) -> Optional[int]: def getPageIndexById(self, page_id: str) -> Optional[int]:
page_idx = None page_idx = None
@ -189,7 +199,35 @@ class WelcomePagesModel(ListModel):
return QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, return QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles,
os.path.join("WelcomePages", page_filename))) os.path.join("WelcomePages", page_filename)))
# FIXME: HACKs for optimization that we don't update the model every time the active machine gets changed.
def _onActiveMachineChanged(self) -> None:
self._application.getMachineManager().globalContainerChanged.disconnect(self._onActiveMachineChanged)
self._initialize(update_should_show_flag = False)
def initialize(self) -> None: def initialize(self) -> None:
self._application.getMachineManager().globalContainerChanged.connect(self._onActiveMachineChanged)
self._initialize()
def _initialize(self, update_should_show_flag: bool = True) -> None:
show_whatsnew_only = False
if update_should_show_flag:
has_active_machine = self._application.getMachineManager().activeMachine is not None
has_app_just_upgraded = self._application.hasJustUpdatedFromOldVersion()
# Only show the what's new dialog if there's no machine and we have just upgraded
show_complete_flow = not has_active_machine
show_whatsnew_only = has_active_machine and has_app_just_upgraded
# FIXME: This is a hack. Because of the circular dependency between MachineManager, ExtruderManager, and
# possibly some others, setting the initial active machine is not done when the MachineManager gets initialized.
# So at this point, we don't know if there will be an active machine or not. It could be that the active machine
# files are corrupted so we cannot rely on Preferences either. This makes sure that once the active machine
# gets changed, this model updates the flags, so it can decide whether to show the welcome flow or not.
should_show_welcome_flow = show_complete_flow or show_whatsnew_only
if should_show_welcome_flow != self._should_show_welcome_flow:
self._should_show_welcome_flow = should_show_welcome_flow
self.shouldShowWelcomeFlowChanged.emit()
# All pages # All pages
all_pages_list = [{"id": "welcome", all_pages_list = [{"id": "welcome",
"page_url": self._getBuiltinWelcomePagePath("WelcomeContent.qml"), "page_url": self._getBuiltinWelcomePagePath("WelcomeContent.qml"),
@ -221,7 +259,11 @@ class WelcomePagesModel(ListModel):
}, },
] ]
self._pages = all_pages_list pages_to_show = all_pages_list
if show_whatsnew_only:
pages_to_show = list(filter(lambda x: x["id"] == "whats_new", all_pages_list))
self._pages = pages_to_show
self.setItems(self._pages) self.setItems(self._pages)
# For convenience, inject the default "next" button text to each item if it's not present. # For convenience, inject the default "next" button text to each item if it's not present.

View File

@ -57,6 +57,7 @@ Item
{ {
text: catalog.i18nc("@title:label", "Printer Settings") text: catalog.i18nc("@title:label", "Printer Settings")
font: UM.Theme.getFont("medium_bold") font: UM.Theme.getFont("medium_bold")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@ -172,6 +173,7 @@ Item
{ {
text: catalog.i18nc("@title:label", "Printhead Settings") text: catalog.i18nc("@title:label", "Printhead Settings")
font: UM.Theme.getFont("medium_bold") font: UM.Theme.getFont("medium_bold")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View File

@ -29,7 +29,8 @@ Cura.MachineAction
width: parent.width width: parent.width
text: catalog.i18nc("@title", "Build Plate Leveling") text: catalog.i18nc("@title", "Build Plate Leveling")
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
font.pointSize: 18 font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@ -41,6 +42,8 @@ Cura.MachineAction
width: parent.width width: parent.width
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "To make sure your prints will come out great, you can now adjust your buildplate. When you click 'Move to Next Position' the nozzle will move to the different positions that can be adjusted.") text: catalog.i18nc("@label", "To make sure your prints will come out great, you can now adjust your buildplate. When you click 'Move to Next Position' the nozzle will move to the different positions that can be adjusted.")
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@ -52,6 +55,8 @@ Cura.MachineAction
width: parent.width width: parent.width
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "For every position; insert a piece of paper under the nozzle and adjust the print build plate height. The print build plate height is right when the paper is slightly gripped by the tip of the nozzle.") text: catalog.i18nc("@label", "For every position; insert a piece of paper under the nozzle and adjust the print build plate height. The print build plate height is right when the paper is slightly gripped by the tip of the nozzle.")
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View File

@ -29,6 +29,7 @@ Cura.MachineAction
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "Please select any upgrades made to this Ultimaker 2.") text: catalog.i18nc("@label", "Please select any upgrades made to this Ultimaker 2.")
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View File

@ -29,6 +29,7 @@ Cura.MachineAction
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
text: catalog.i18nc("@label","Please select any upgrades made to this Ultimaker Original") text: catalog.i18nc("@label","Please select any upgrades made to this Ultimaker Original")
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View File

@ -794,6 +794,7 @@ UM.MainWindow
title: catalog.i18nc("@title:window", "Add Printer") title: catalog.i18nc("@title:window", "Add Printer")
model: CuraApplication.getAddPrinterPagesModel() model: CuraApplication.getAddPrinterPagesModel()
progressBarVisible: false progressBarVisible: false
hasCancelButton: true
} }
Cura.WizardDialog Cura.WizardDialog
@ -802,6 +803,7 @@ UM.MainWindow
title: catalog.i18nc("@title:window", "What's New") title: catalog.i18nc("@title:window", "What's New")
model: CuraApplication.getWhatsNewPagesModel() model: CuraApplication.getWhatsNewPagesModel()
progressBarVisible: false progressBarVisible: false
hasCancelButton: false
} }
Connections Connections

View File

@ -59,6 +59,7 @@ UM.TooltipArea
anchors.verticalCenter: comboBox.verticalCenter anchors.verticalCenter: comboBox.verticalCenter
visible: text != "" visible: text != ""
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View File

@ -41,6 +41,7 @@ UM.TooltipArea
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
font: UM.Theme.getFont("medium_bold") font: UM.Theme.getFont("medium_bold")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@ -59,13 +60,16 @@ UM.TooltipArea
hoverEnabled: true hoverEnabled: true
selectByMouse: true selectByMouse: true
text: (propertyProvider.properties.value) ? propertyProvider.properties.value : ""
font: UM.Theme.getFont("fixed") font: UM.Theme.getFont("fixed")
renderType: Text.NativeRendering renderType: Text.NativeRendering
text: (propertyProvider.properties.value) ? propertyProvider.properties.value : "" color: UM.Theme.getColor("text")
wrapMode: TextEdit.NoWrap wrapMode: TextEdit.NoWrap
background: Rectangle background: Rectangle
{ {
color: UM.Theme.getColor("main_background")
border.color: border.color:
{ {
if (!gcodeTextArea.enabled) if (!gcodeTextArea.enabled)

View File

@ -66,6 +66,7 @@ UM.TooltipArea
anchors.verticalCenter: textFieldWithUnit.verticalCenter anchors.verticalCenter: textFieldWithUnit.verticalCenter
visible: text != "" visible: text != ""
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@ -135,6 +136,7 @@ UM.TooltipArea
hoverEnabled: true hoverEnabled: true
selectByMouse: true selectByMouse: true
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
// When the textbox gets focused by TAB, select all text // When the textbox gets focused by TAB, select all text

View File

@ -53,6 +53,7 @@ UM.TooltipArea
anchors.verticalCenter: checkBox.verticalCenter anchors.verticalCenter: checkBox.verticalCenter
visible: text != "" visible: text != ""
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View File

@ -85,6 +85,8 @@ Item
{ {
id: machineList id: machineList
cacheBuffer: 0 // Workaround for https://bugreports.qt.io/browse/QTBUG-49224
model: UM.DefinitionContainersModel model: UM.DefinitionContainersModel
{ {
id: machineDefinitionsModel id: machineDefinitionsModel
@ -142,6 +144,7 @@ Item
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
text: button.text text: button.text
font: UM.Theme.getFont("default_bold") font: UM.Theme.getFont("default_bold")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
} }
@ -200,9 +203,10 @@ Item
Label Label
{ {
text: catalog.i18nc("@label", "Printer Name") text: catalog.i18nc("@label", "Printer name")
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@ -213,9 +217,12 @@ Item
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
width: (parent.width / 2) | 0 width: (parent.width / 2) | 0
placeholderText: catalog.i18nc("@text", "Please give your printer a name") placeholderText: catalog.i18nc("@text", "Please give your printer a name")
maximumLength: 40
// Make sure that the fill is not empty validator: RegExpValidator
validator: RegExpValidator { regExp: /.+/ } {
regExp: printerNameTextField.machineNameValidator.machineNameRegex
}
property var machineNameValidator: Cura.MachineNameValidator { }
} }
} }
} }

View File

@ -72,6 +72,8 @@ Item
section.criteria: ViewSection.FullString section.criteria: ViewSection.FullString
section.delegate: sectionHeading section.delegate: sectionHeading
cacheBuffer: 0 // Workaround for https://bugreports.qt.io/browse/QTBUG-49224
Component.onCompleted: Component.onCompleted:
{ {
// Select the first one that's not "unknown" by default. // Select the first one that's not "unknown" by default.

View File

@ -61,6 +61,7 @@ Item
anchors.top: parent.top anchors.top: parent.top
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
text: catalog.i18nc("@label", "Enter the IP address or hostname of your printer on the network.") text: catalog.i18nc("@label", "Enter the IP address or hostname of your printer on the network.")
} }
@ -129,6 +130,7 @@ Item
anchors.top: parent.top anchors.top: parent.top
anchors.margins: UM.Theme.getSize("default_margin").width anchors.margins: UM.Theme.getSize("default_margin").width
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
visible: visible:
@ -162,6 +164,7 @@ Item
id: printerNameLabel id: printerNameLabel
anchors.top: parent.top anchors.top: parent.top
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
text: "???" text: "???"
@ -175,14 +178,53 @@ Item
columns: 2 columns: 2
columnSpacing: UM.Theme.getSize("default_margin").width columnSpacing: UM.Theme.getSize("default_margin").width
Label { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Type"); renderType: Text.NativeRendering } Label
Label { id: typeText; font: UM.Theme.getFont("default"); text: "?"; renderType: Text.NativeRendering } {
text: catalog.i18nc("@label", "Type")
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
}
Label
{
id: typeText
text: "?"
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
}
Label { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Firmware version"); renderType: Text.NativeRendering } Label
Label { id: firmwareText; font: UM.Theme.getFont("default"); text: "0.0.0.0"; renderType: Text.NativeRendering } {
text: catalog.i18nc("@label", "Firmware version")
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
}
Label
{
id: firmwareText
text: "0.0.0.0"
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
}
Label { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Address"); renderType: Text.NativeRendering } Label
Label { id: addressText; font: UM.Theme.getFont("default"); text: "0.0.0.0"; renderType: Text.NativeRendering } {
text: catalog.i18nc("@label", "Address")
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
}
Label
{
id: addressText
text: "0.0.0.0"
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
}
Connections Connections
{ {

View File

@ -52,7 +52,6 @@ Item
topMargin: UM.Theme.getSize("default_margin").height topMargin: UM.Theme.getSize("default_margin").height
} }
// Pictures and texts are arranged using Columns with spacing. The whole picture and text area is centered in // Pictures and texts are arranged using Columns with spacing. The whole picture and text area is centered in
// the cloud contents area. // the cloud contents area.
Column Column
@ -105,6 +104,7 @@ Item
} }
textFormat: Text.RichText textFormat: Text.RichText
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
} }

View File

@ -71,6 +71,7 @@ Item
textFormat: Text.RichText textFormat: Text.RichText
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
MouseArea MouseArea

View File

@ -21,7 +21,7 @@ Cura.RoundedRectangle
border.width: UM.Theme.getSize("default_lining").width border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining") border.color: UM.Theme.getColor("lining")
color: hovered ? UM.Theme.getColor("secondary_button_hover") : UM.Theme.getColor("secondary_button") color: UM.Theme.getColor("secondary")
radius: UM.Theme.getSize("default_radius").width radius: UM.Theme.getSize("default_radius").width
cornerSide: contentShown ? Cura.RoundedRectangle.Direction.Up : Cura.RoundedRectangle.Direction.All cornerSide: contentShown ? Cura.RoundedRectangle.Direction.Up : Cura.RoundedRectangle.Direction.All

View File

@ -49,7 +49,7 @@ Item
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: UM.Theme.getSize("expandable_component_content_header").height height: UM.Theme.getSize("expandable_component_content_header").height
rightIconSource: contentShown ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_right") rightIconSource: contentShown ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left")
contentShown: base.contentShown contentShown: base.contentShown
} }

View File

@ -44,6 +44,7 @@ Item
textFormat: Text.RichText textFormat: Text.RichText
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View File

@ -46,6 +46,7 @@ Item
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
text: catalog.i18nc("@text", "Please follow these steps to set up\nUltimaker Cura. This will only take a few moments.") text: catalog.i18nc("@text", "Please follow these steps to set up\nUltimaker Cura. This will only take a few moments.")
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View File

@ -24,11 +24,14 @@ Window
minimumWidth: 580 * screenScaleFactor minimumWidth: 580 * screenScaleFactor
minimumHeight: 600 * screenScaleFactor minimumHeight: 600 * screenScaleFactor
maximumWidth: minimumWidth
maximumHeight: minimumHeight
color: UM.Theme.getColor("main_background") color: UM.Theme.getColor("main_background")
property var model: null // Needs to be set by whoever is using this dialog. property var model: null // Needs to be set by whoever is using this dialog.
property alias progressBarVisible: wizardPanel.progressBarVisible property alias progressBarVisible: wizardPanel.progressBarVisible
property alias hasCancelButton: cancelButton.visible
onVisibilityChanged: onVisibilityChanged:
{ {
@ -51,4 +54,20 @@ Window
target: model target: model
onAllFinished: dialog.hide() onAllFinished: dialog.hide()
} }
Cura.SecondaryButton
{
id: cancelButton
text: catalog.i18nc("@button", "Cancel")
visible: false
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.margins: UM.Theme.getSize("default_margin").width
enabled: true
onClicked: dialog.visible = false
}
} }

View File

@ -70,6 +70,7 @@ CheckBox
leftPadding: control.indicator.width + control.spacing leftPadding: control.indicator.width + control.spacing
text: control.text text: control.text
font: control.font font: control.font
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }

View File

@ -49,6 +49,7 @@ RadioButton
leftPadding: radioButton.indicator.width + radioButton.spacing leftPadding: radioButton.indicator.width + radioButton.spacing
text: radioButton.text text: radioButton.text
font: radioButton.font font: radioButton.font
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
} }

View File

@ -19,6 +19,7 @@ ScrollView
background: Rectangle // Border background: Rectangle // Border
{ {
color: UM.Theme.getColor("main_background")
border.color: UM.Theme.getColor("lining") border.color: UM.Theme.getColor("lining")
border.width: UM.Theme.getSize("default_lining").width border.width: UM.Theme.getSize("default_lining").width
} }
@ -27,6 +28,7 @@ ScrollView
{ {
id: _textArea id: _textArea
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
textFormat: TextEdit.PlainText textFormat: TextEdit.PlainText
renderType: Text.NativeRendering renderType: Text.NativeRendering
selectByMouse: true selectByMouse: true

View File

@ -20,6 +20,7 @@ TextField
hoverEnabled: true hoverEnabled: true
selectByMouse: true selectByMouse: true
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
states: [ states: [
@ -49,6 +50,8 @@ TextField
{ {
id: backgroundRectangle id: backgroundRectangle
color: UM.Theme.getColor("main_background")
anchors.margins: Math.round(UM.Theme.getSize("default_lining").width) anchors.margins: Math.round(UM.Theme.getSize("default_lining").width)
radius: UM.Theme.getSize("setting_control_radius").width radius: UM.Theme.getSize("setting_control_radius").width

View File

@ -94,8 +94,8 @@
"action_button_active": [39, 44, 48, 30], "action_button_active": [39, 44, 48, 30],
"action_button_active_text": [255, 255, 255, 255], "action_button_active_text": [255, 255, 255, 255],
"action_button_active_border": [255, 255, 255, 100], "action_button_active_border": [255, 255, 255, 100],
"action_button_disabled": [39, 44, 48, 255], "action_button_disabled": [19, 24, 28, 255],
"action_button_disabled_text": [255, 255, 255, 80], "action_button_disabled_text": [200, 200, 200, 80],
"action_button_disabled_border": [255, 255, 255, 30], "action_button_disabled_border": [255, 255, 255, 30],
"scrollbar_background": [39, 44, 48, 0], "scrollbar_background": [39, 44, 48, 0],