Many many changes. Homing is working fully
This commit is contained in:
49
KlipperScreen.config
Normal file
49
KlipperScreen.config
Normal file
@@ -0,0 +1,49 @@
|
||||
[
|
||||
{
|
||||
"name": "Home",
|
||||
"icon": "home",
|
||||
"items": [
|
||||
{
|
||||
"name": "Home All",
|
||||
"icon": "home",
|
||||
"method": "post_printer_gcode",
|
||||
"params": {"script": "G28"}
|
||||
},
|
||||
{
|
||||
"name": "Home X",
|
||||
"icon": "home-x",
|
||||
"method": "post_printer_gcode",
|
||||
"params": {"script": "G28 X"}
|
||||
},
|
||||
{
|
||||
"name": "Home Y",
|
||||
"icon": "home-y",
|
||||
"method": "post_printer_gcode",
|
||||
"params": {"script": "G28 Y"}
|
||||
},
|
||||
{
|
||||
"name": "Home Z",
|
||||
"icon": "home-z",
|
||||
"method": "post_printer_gcode",
|
||||
"params": {"script": "G28 Z"}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Filament" ,
|
||||
"icon": "filament"
|
||||
},
|
||||
{
|
||||
"name": "Move",
|
||||
"icon": "move"
|
||||
},
|
||||
{
|
||||
"name": "Menu",
|
||||
"icon": "actions"
|
||||
},
|
||||
{
|
||||
"name": "Control",
|
||||
"icon": "control"
|
||||
}
|
||||
|
||||
]
|
46
KlippyGtk.py
Normal file
46
KlippyGtk.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import gi
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, Gdk, GLib
|
||||
|
||||
class KlippyGtk:
|
||||
labels = {}
|
||||
|
||||
#def __init__ (self):
|
||||
|
||||
@staticmethod
|
||||
def ImageLabel(image_name, text):
|
||||
box1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, relief=2)
|
||||
image = Gtk.Image()
|
||||
#TODO: update file reference
|
||||
image.set_from_file("/opt/printer/OctoScreen/styles/z-bolt/images/" + str(image_name) + ".svg")
|
||||
label = Gtk.Label()
|
||||
label.set_text(text)
|
||||
box1.add(image)
|
||||
box1.add(label)
|
||||
return box1
|
||||
|
||||
@staticmethod
|
||||
def ButtonImage(image_name, label, style=False):
|
||||
img = Gtk.Image.new_from_file("/opt/printer/OctoScreen/styles/z-bolt/images/" + str(image_name) + ".svg")
|
||||
|
||||
b = Gtk.Button(label=label)
|
||||
#b.props.relief = Gtk.RELIEF_NONE
|
||||
b.set_image(img)
|
||||
b.set_hexpand(True)
|
||||
b.set_vexpand(True)
|
||||
b.set_can_focus(False)
|
||||
b.set_image_position(Gtk.PositionType.TOP)
|
||||
b.set_always_show_image(True)
|
||||
|
||||
if style != False:
|
||||
ctx = b.get_style_context()
|
||||
ctx.add_class(style)
|
||||
|
||||
return b
|
||||
|
||||
@staticmethod
|
||||
def formatTemperatureString(temp, target):
|
||||
if (target > temp-2 and target < temp+2) or round(target,0) == 0:
|
||||
return str(round(temp,2)) + "C"
|
||||
return str(round(temp,2)) + "C -> " + str(round(target,2)) + "C"
|
81
KlippyWebsocket.py
Normal file
81
KlippyWebsocket.py
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import gi
|
||||
import time
|
||||
import threading
|
||||
|
||||
import json
|
||||
import requests
|
||||
import websocket
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, Gdk, GLib
|
||||
|
||||
#f = open("/home/pi/.moonraker_api_key", "r")
|
||||
api_key = "" #f.readline()
|
||||
#f.close()
|
||||
|
||||
api = {
|
||||
"printer_info": {
|
||||
"url": "/printer/info",
|
||||
"method": "get_printer_info"
|
||||
},
|
||||
"apikey": {
|
||||
"url": "/access/api_key"
|
||||
},
|
||||
"oneshot_token": {
|
||||
"url": "/access/oneshot_token"
|
||||
}
|
||||
}
|
||||
class KlippyWebsocket(threading.Thread):
|
||||
_req_id = 0
|
||||
def __init__(self, callback):
|
||||
threading.Thread.__init__(self)
|
||||
self._callback = callback
|
||||
|
||||
self._url = "127.0.0.1:7125"
|
||||
|
||||
def connect (self):
|
||||
r = requests.get("http://" + self._url + api['oneshot_token']['url'], headers={"x-api-key":api_key})
|
||||
if r.status_code != 200:
|
||||
print "Failed to retrieve oneshot token"
|
||||
return
|
||||
|
||||
token = json.loads(r.content)['result']
|
||||
self.ws_url = "ws://" + self._url + "/websocket?token=" + token
|
||||
self.ws = websocket.WebSocketApp(self.ws_url,
|
||||
on_open = self.on_open,
|
||||
on_message = self.on_message,
|
||||
on_error = self.on_error,
|
||||
on_close = self.on_close,
|
||||
)
|
||||
self.ws.on_open = self.on_open
|
||||
self._wst = threading.Thread(target=self.ws.run_forever)
|
||||
self._wst.daemon = True
|
||||
self._wst.start()
|
||||
|
||||
def on_message(self, message):
|
||||
result = json.loads(message)
|
||||
print json.dumps(result, indent=2)
|
||||
GLib.idle_add(self._callback, result['method'], result['params'][0])
|
||||
|
||||
def send_method(self, method, params):
|
||||
#print "{jsonrpc: \"2.0\", method: \"" + str(method) + "\", params: " + json.dumps(params) + ", id: \"2\"}"
|
||||
data = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": method,
|
||||
"params": params,
|
||||
"id": "2"
|
||||
}
|
||||
print json.dumps(data)
|
||||
self.ws.send(json.dumps(data))
|
||||
|
||||
def on_open(self, ws):
|
||||
print "### ws open ###"
|
||||
self.ws.send('{jsonrpc: "2.0", method: "post_printer_objects_subscription", params: {extruder: ["temperature","target"], toolhead: ["position", "status"]}, id: "1"}')
|
||||
|
||||
def on_close(self, ws):
|
||||
print "### ws closed ###"
|
||||
|
||||
def on_error(self, ws, error):
|
||||
print(error)
|
1
panels/__init__.py
Normal file
1
panels/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from idle_status import *
|
48
panels/idle_status.py
Normal file
48
panels/idle_status.py
Normal file
@@ -0,0 +1,48 @@
|
||||
import gi
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, Gdk, GLib
|
||||
|
||||
from KlippyGtk import KlippyGtk
|
||||
|
||||
class IdleStatusPanel:
|
||||
_screen = None
|
||||
labels = {}
|
||||
|
||||
def __init__(self, screen):
|
||||
self._screen = screen
|
||||
print "init"
|
||||
|
||||
|
||||
# def initialize(self):
|
||||
# box1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
# image = Gtk.Image()
|
||||
# #TODO: update file reference
|
||||
# image.set_from_file("/opt/printer/OctoScreen/styles/z-bolt/images/bed.svg")
|
||||
# label = Gtk.Label()
|
||||
# label.set_text("0C / 0C")
|
||||
# self.bed_temp_label = label
|
||||
# box1.add(image)
|
||||
# box1.add(self.bed_temp_label)
|
||||
#
|
||||
# return box1
|
||||
def initialize(self):
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
|
||||
grid = Gtk.Grid()
|
||||
grid.set_row_homogeneous(True)
|
||||
grid.set_column_homogeneous(True)
|
||||
|
||||
for i in range(self._screen.number_tools):
|
||||
self.labels["tool" + str(i)] = KlippyGtk.ButtonImage("extruder-"+str(i+1), "0C / 0C")
|
||||
grid.attach(self.labels["tool" + str(i)], 0, 0, 1, 1)
|
||||
|
||||
self.labels['bed'] = KlippyGtk.ButtonImage("bed", "0C / 0C")
|
||||
grid.attach(self.labels['bed'], 0, 1, 1, 1)
|
||||
#box.add(KlippyGtk.ButtonImage("bed", "0C / 0C"))
|
||||
|
||||
box.add(grid)
|
||||
return box
|
||||
|
||||
def update_temp(self, dev, temp, target):
|
||||
if self.labels.has_key(dev):
|
||||
self.labels[dev].set_label(KlippyGtk.formatTemperatureString(temp, target))
|
234
screen.py
234
screen.py
@@ -1,42 +1,63 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import gi
|
||||
import time
|
||||
import threading
|
||||
|
||||
import json
|
||||
import requests
|
||||
import websocket
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, Gdk
|
||||
from gi.repository import Gtk, Gdk, GLib
|
||||
|
||||
from KlippyWebsocket import KlippyWebsocket
|
||||
from KlippyGtk import KlippyGtk
|
||||
from panels import IdleStatusPanel
|
||||
|
||||
config = "/opt/printer/KlipperScreen/KlipperScreen.config"
|
||||
|
||||
class KlipperScreen(Gtk.Window):
|
||||
""" Class for creating a screen for Klipper via HDMI """
|
||||
currentPanel = None
|
||||
bed_temp_label = None
|
||||
number_tools = 1
|
||||
|
||||
panels = {}
|
||||
_cur_panels = []
|
||||
|
||||
def __init__(self):
|
||||
self.read_config()
|
||||
self.init_style()
|
||||
Gtk.Window.__init__(self)
|
||||
|
||||
self.set_default_size(Gdk.Screen.get_width(Gdk.Screen.get_default()),Gdk.Screen.get_height(Gdk.Screen.get_default()))
|
||||
self.set_default_size(Gdk.Screen.get_width(Gdk.Screen.get_default()), Gdk.Screen.get_height(Gdk.Screen.get_default()))
|
||||
|
||||
r = requests.get("http://127.0.0.1:7125/printer/info") #, headers={"x-api-key":api_key})
|
||||
if r.status_code != 200:
|
||||
self.printer_initializing()
|
||||
self.create_websocket()
|
||||
return
|
||||
|
||||
#self.splash_screen()
|
||||
data = json.loads(r.content)
|
||||
|
||||
if data['result']['is_ready'] != True:
|
||||
self.printer_initializing()
|
||||
self.create_websocket()
|
||||
return
|
||||
|
||||
self.create_websocket()
|
||||
self.main_panel()
|
||||
|
||||
self.box = Gtk.Box(spacing=6)
|
||||
#self.add(self.box)
|
||||
|
||||
self.button1 = Gtk.Button(label="Hello")
|
||||
self.button1.connect("clicked", self.on_button1_clicked)
|
||||
#self.box.pack_start(self.button1, True, True, 0)
|
||||
def read_config (self):
|
||||
with open(config) as config_file:
|
||||
self._config = json.load(config_file)
|
||||
|
||||
self.button2 = Gtk.Button(label="Goodbye")
|
||||
self.button2.connect("clicked", self.on_button2_clicked)
|
||||
#self.box.pack_start(self.button2, True, True, 0)
|
||||
|
||||
def init_style(self):
|
||||
cssdata = ""
|
||||
with open ('/home/pi/style.css', 'r' ) as file:
|
||||
cssdata = file.read()
|
||||
|
||||
style_provider = Gtk.CssProvider()
|
||||
style_provider.load_from_path("/home/pi/style.css")
|
||||
style_provider.load_from_path("/opt/printer/KlipperScreen/style.css")
|
||||
|
||||
Gtk.StyleContext.add_provider_for_screen(
|
||||
Gdk.Screen.get_default(),
|
||||
@@ -45,14 +66,15 @@ class KlipperScreen(Gtk.Window):
|
||||
)
|
||||
|
||||
def splash_screen(self):
|
||||
if "splash_screen" not in self.panels:
|
||||
image = Gtk.Image()
|
||||
#TODO: update file reference
|
||||
image.set_from_file("/opt/printer/OctoScreen/styles/z-bolt/images/logo.png")
|
||||
|
||||
#label = Gtk.Label()
|
||||
#label.set_text("Initializing printer...")
|
||||
label = Gtk.Button(label="Initializing printer...")
|
||||
label.connect("clicked", self.printer_initialize)
|
||||
label = Gtk.Label()
|
||||
label.set_text("Initializing printer...")
|
||||
#label = Gtk.Button(label="Initializing printer...")
|
||||
#label.connect("clicked", self.printer_initialize)
|
||||
|
||||
main = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=15)
|
||||
main.pack_start(image, True, True, 10)
|
||||
@@ -60,33 +82,163 @@ class KlipperScreen(Gtk.Window):
|
||||
|
||||
box = Gtk.VBox()
|
||||
box.add(main)
|
||||
self.add(box)
|
||||
self.currentPanel = box
|
||||
self.panels['splash_screen'] = box
|
||||
|
||||
self.add(self.panels['splash_screen'])
|
||||
self.show_all()
|
||||
self._cur_panels = ['splash_screen']
|
||||
|
||||
def create_websocket(self):
|
||||
self._ws = KlippyWebsocket(self._websocket_callback)
|
||||
self._ws.connect()
|
||||
self._curr = 0
|
||||
|
||||
def main_panel (self):
|
||||
box = Gtk.Box(spacing=6)
|
||||
if "main_panel" not in self.panels:
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
|
||||
|
||||
box.add(self.gtk_ButtonImage("/opt/printer/OctoScreen/styles/z-bolt/images/home.svg", "Home"))
|
||||
box.add(self.gtk_ButtonImage("/opt/printer/OctoScreen/styles/z-bolt/images/filament.svg", "Filament"))
|
||||
self.add(box)
|
||||
self.currentPanel = box
|
||||
grid = Gtk.Grid()
|
||||
grid.set_row_homogeneous(True)
|
||||
grid.set_column_homogeneous(True)
|
||||
|
||||
self.panels['idle_status'] = IdleStatusPanel(self)
|
||||
|
||||
|
||||
def gtk_ButtonImage (self, image, label):
|
||||
img = Gtk.Image.new_from_file(image)
|
||||
grid.attach(self.panels['idle_status'].initialize(), 0, 0, 1, 1)
|
||||
#grid.attach(box2, 1, 0, 1, 1)
|
||||
|
||||
b = Gtk.Button(label=label)
|
||||
b.set_image(img)
|
||||
b.set_image_position(Gtk.PositionType.TOP)
|
||||
b.set_always_show_image(True)
|
||||
ctx = b.get_style_context()
|
||||
ctx.add_class("color1")
|
||||
#button.set_vertical_expand(True)
|
||||
#button.set_h_expand(True)
|
||||
return b
|
||||
|
||||
def printer_initialize(self, widget):
|
||||
self.remove(self.currentPanel)
|
||||
grid.attach(self.arrangeMenuItems(self._config,2), 1, 0, 1, 1)
|
||||
|
||||
self.panels['main_screen'] = grid
|
||||
|
||||
print ("### Adding main panel")
|
||||
self.add(self.panels['main_screen'])
|
||||
self.show_all()
|
||||
self._cur_panels.append("main_screen")
|
||||
|
||||
def _go_to_submenu(self, widget, menu):
|
||||
print "#### Go to submenu " + str(menu)
|
||||
self._remove_current_panel(False)
|
||||
|
||||
# Find current menu item
|
||||
panels = list(self._cur_panels)
|
||||
cur_item = self._find_current_menu_item(menu, self._config, panels.pop(0))
|
||||
menu = cur_item['items']
|
||||
|
||||
grid = self.arrangeMenuItems(menu, 4)
|
||||
|
||||
b = KlippyGtk.ButtonImage('back', 'Back')
|
||||
b.connect("clicked", self._menu_go_back)
|
||||
grid.attach(b, 4, 2, 1, 1)
|
||||
|
||||
self._cur_panels.append(cur_item['name']) #str(cur_item['name']))
|
||||
self.panels[cur_item['name']] = grid
|
||||
self.add(self.panels[cur_item['name']])
|
||||
self.show_all()
|
||||
|
||||
|
||||
|
||||
def _find_current_menu_item(self, menu, items, names):
|
||||
# TODO: Make recursive
|
||||
return items[menu]
|
||||
|
||||
|
||||
def _remove_all_panels(self):
|
||||
while len(self._cur_panels) > 0:
|
||||
self._remove_current_panel()
|
||||
|
||||
def _remove_current_panel(self, pop=True):
|
||||
print "1 " + str(self._cur_panels)
|
||||
print self.panels.keys()
|
||||
if len(self._cur_panels) > 0:
|
||||
self.remove(
|
||||
self.panels[
|
||||
self._cur_panels[-1]
|
||||
]
|
||||
)
|
||||
if pop == True:
|
||||
print "Popping _cur_panels"
|
||||
self._cur_panels.pop()
|
||||
if len(self._cur_panels) > 0:
|
||||
self.add(self.panels[self._cur_panels[-1]])
|
||||
self.show_all()
|
||||
|
||||
def _menu_go_back (self, widget):
|
||||
print "#### Menu go back"
|
||||
self._remove_current_panel()
|
||||
|
||||
def _websocket_callback(self, action, data):
|
||||
if action == "notify_klippy_state_changed":
|
||||
if data == "ready":
|
||||
print "### Going to ready state"
|
||||
self.printer_ready()
|
||||
elif data == "disconnect" or data == "shutdown":
|
||||
print "### Going to disconnected state"
|
||||
self.printer_initializing()
|
||||
|
||||
elif action == "notify_status_update":
|
||||
#print data
|
||||
if "idle_status" in self.panels:
|
||||
if "heater_bed" in data:
|
||||
self.panels['idle_status'].update_temp(
|
||||
"bed",
|
||||
round(data['heater_bed']['temperature'],1),
|
||||
round(data['heater_bed']['target'],1)
|
||||
)
|
||||
if "extruder" in data and data['extruder'] != "extruder":
|
||||
self.panels['idle_status'].update_temp(
|
||||
"tool0",
|
||||
round(data['extruder']['temperature'],1),
|
||||
round(data['extruder']['target'],1)
|
||||
)
|
||||
|
||||
|
||||
def set_bed_temp (self, num, target):
|
||||
print str(num) + "C / " + str(target) + "C"
|
||||
if self.bed_temp_label == None:
|
||||
return
|
||||
self.bed_temp_label.set_text(str(num) + "C / " + str(target) + "C")
|
||||
|
||||
def arrangeMenuItems (self, items, columns):
|
||||
grid = Gtk.Grid()
|
||||
grid.set_row_homogeneous(True)
|
||||
grid.set_column_homogeneous(True)
|
||||
|
||||
l = len(items)
|
||||
i = 0
|
||||
print items
|
||||
for i in range(l):
|
||||
col = i % columns
|
||||
row = round(i/columns, 0)
|
||||
width = 1
|
||||
#if i+1 == l and l%2 == 1:
|
||||
# width = 2
|
||||
b = KlippyGtk.ButtonImage(
|
||||
items[i]['icon'], items[i]['name'], "color"+str((i%4)+1)
|
||||
)
|
||||
if "items" in items[i]:
|
||||
b.connect("clicked", self._go_to_submenu, i)
|
||||
elif "method" in items[i]:
|
||||
params = items[i]['params'] if "params" in items[i] else {}
|
||||
b.connect("clicked", self._send_action, items[i]['method'], params)
|
||||
|
||||
|
||||
grid.attach(b, col, row, 1, width)
|
||||
|
||||
i += 1
|
||||
|
||||
return grid
|
||||
|
||||
def _send_action(self, widget, method, params):
|
||||
self._ws.send_method(method, params)
|
||||
|
||||
def printer_initializing(self):
|
||||
self._remove_all_panels()
|
||||
self.splash_screen()
|
||||
|
||||
def printer_ready(self):
|
||||
self._remove_all_panels()
|
||||
self.main_panel()
|
||||
|
||||
def on_button1_clicked(self, widget):
|
||||
@@ -101,9 +253,7 @@ win.connect("destroy", Gtk.main_quit)
|
||||
win.show_all()
|
||||
Gtk.main()
|
||||
|
||||
|
||||
#win = KlipperScreen()
|
||||
#win.connect("destroy", Gtk.main_quit)
|
||||
#win.show_all()
|
||||
#Gtk.main()
|
||||
|
||||
|
158
style.css
Normal file
158
style.css
Normal file
@@ -0,0 +1,158 @@
|
||||
/* * {
|
||||
|
||||
} */
|
||||
|
||||
window {
|
||||
background-color: #13181C;
|
||||
-gtk-icon-shadow: none;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
scrollbar, scrollbar button {
|
||||
border: none;
|
||||
background-color: #13181C;
|
||||
}
|
||||
|
||||
scrollbar slider {
|
||||
min-width: 88px;
|
||||
border-radius: 15px;
|
||||
background-color: #404E57;
|
||||
}
|
||||
|
||||
progress, trough {
|
||||
min-height: 20px;
|
||||
font-size: 50px;
|
||||
}
|
||||
|
||||
progress {
|
||||
background-color: #00C9B4;
|
||||
font-size: 50px;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.printing-progress-bar{
|
||||
font-size: 60px;
|
||||
color: #00C9B4;
|
||||
}
|
||||
|
||||
.printing-state {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
button {
|
||||
background-image: none;
|
||||
background-color: #13181C;
|
||||
margin: 5px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 0;
|
||||
border: 0px solid #000;
|
||||
color: #fff;
|
||||
-gtk-icon-shadow: none;
|
||||
}
|
||||
|
||||
button:active {
|
||||
background-color: #304C62;
|
||||
}
|
||||
|
||||
button.color1 {
|
||||
border-bottom: 8px solid #ED6500;
|
||||
}
|
||||
|
||||
button.color2 {
|
||||
border-bottom: 8px solid #B10080;
|
||||
}
|
||||
|
||||
button.color3 {
|
||||
border-bottom: 8px solid #009384;
|
||||
}
|
||||
|
||||
button.color4 {
|
||||
border-bottom: 8px solid #A7E100;
|
||||
}
|
||||
|
||||
button.active {
|
||||
background-color: #20303D;
|
||||
}
|
||||
|
||||
button.file-list {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
entry {
|
||||
font-size: 30px;
|
||||
background-color: #20292F;
|
||||
border-radius: 0;
|
||||
padding-left: 1em;
|
||||
margin-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
button.keyboard {
|
||||
font-size: 30px;
|
||||
margin: 0px;
|
||||
/* margin-bottom:10px; */
|
||||
}
|
||||
|
||||
.dialog {
|
||||
border: 2px solid black;
|
||||
font-size: 20px;
|
||||
padding: 50px;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.dialog button {
|
||||
padding: 30px 50px 30px 50px;
|
||||
border-bottom: 8px solid #009384;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
border: 2px solid black;
|
||||
font-size: 20px;
|
||||
padding: 50px;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.dialog button {
|
||||
padding: 30px 50px 30px 50px;
|
||||
border-bottom: 8px solid #009384;
|
||||
}
|
||||
|
||||
.message {
|
||||
border: 2px solid #981E1F;
|
||||
font-size: 20px;
|
||||
padding: 50px;
|
||||
color: #FFF;
|
||||
background-color: #981E1F;
|
||||
}
|
||||
|
||||
.message button {
|
||||
background-color: #FFF;
|
||||
color: #000;
|
||||
padding: 40px 50px 40px 50px;
|
||||
}
|
||||
|
||||
.notification {
|
||||
background-clip: padding-box;
|
||||
padding: 5px;
|
||||
border-radius: 0 0 5px 5px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.warning {
|
||||
background-color: rgba(30, 204, 39, 0.7);
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: rgba(204, 30, 30, 0.7);
|
||||
}
|
||||
|
||||
.printing-status-label {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 3px;
|
||||
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
opacity: 0;
|
||||
}
|
Reference in New Issue
Block a user