Reno is the second iteration of the AWMTK-powered AwesomeWM config.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

444 lines
17 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. -- This file is part of Reno desktop.
  2. --
  3. -- Reno desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
  4. --
  5. -- Reno desktop is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  6. --
  7. -- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
  8. -- RenoTK (formerly AWMTK2) - Template/Granular styling library for Reno
  9. local wibox = require("wibox")
  10. local awful = require("awful")
  11. local gears = require("gears")
  12. local beautiful = require("beautiful")
  13. beautiful.widgets = beautiful.widgets or {}
  14. beautiful.templates = beautiful.templates or {}
  15. local awmtk = {}
  16. -- {{{ Utils
  17. awmtk.create_delta = function(name,instance_delta,class_delta,parent_delta)
  18. -- To save memory, we create proxies for lower layers called "deltas"
  19. -- This function creates that proxy layer using metatables
  20. -- Fun story - i used instance_delta instead of {} at first.
  21. -- The results were horrifying and confusing.
  22. return setmetatable({},{
  23. __index = function(self,k)
  24. -- Per-instance overrides are top priority
  25. if rawget(instance_delta,k) then
  26. return rawget(instance_delta,k)
  27. -- Class-wide overrides are second in priority
  28. elseif type(class_delta[name]) == "table"
  29. and rawget(class_delta[name],k) then
  30. return rawget(class_delta[name],k)
  31. -- Parent is fallback
  32. elseif parent_delta[k] then
  33. return parent_delta[k]
  34. end
  35. end
  36. })
  37. end
  38. awmtk.create_style = function(name,parent,overrides)
  39. -- A style is essentially a layer of deltas upon the previous (parent) style
  40. local new_style = {}
  41. local odelta = (overrides and overrides[name]) or {}
  42. local cdelta = beautiful.widgets[name] or {}
  43. for name,parent_class in pairs(parent) do
  44. new_style[name] = awmtk.create_delta(
  45. name,
  46. odelta,
  47. cdelta,
  48. parent_class
  49. )
  50. end
  51. return new_style
  52. end
  53. awmtk.create_template_lib = function(name,parent,overrides)
  54. -- same thing but beautiful.templates
  55. return awmtk.create_delta(
  56. name,
  57. overrides or {},
  58. beautiful.templates or {},
  59. parent
  60. )
  61. end
  62. awmtk.build_templates = function(templates,style)
  63. local new_templates = {}
  64. for name,template in pairs(awmtk.proto_templates) do
  65. new_templates[name] = templates[name](style)
  66. end
  67. return new_templates
  68. end
  69. awmtk.merge = gears.table.join
  70. -- }}}
  71. -- {{{ Default style
  72. -- Prototype style
  73. -- Notice that it's not awmtk.default style - it's used as a base for default.
  74. awmtk.proto_style = {
  75. base = setmetatable({
  76. -- { Backgrounds
  77. -- custom background color for highlighting elements
  78. bg_highlight = beautiful.bg_highlight or beautiful.bg_focus,
  79. -- allow more complex themes to define background images
  80. bgimage_focus = beautiful.bgimage_focus,
  81. bgimage_normal = beautiful.bgimage_normal,
  82. -- }
  83. -- { Borders
  84. -- Borders for popups
  85. shape_border_width = beautiful.shape_border_width or 0,
  86. shape_border_color = beautiful.shape_border_color or beautiful.bg_normal,
  87. -- }
  88. -- { Callbacks
  89. -- a tiny bit more complex thing to account for more extensibility
  90. -- the stub functions do nothing - you should implement functionality inside theme
  91. onpress = function() end,
  92. onrelease = function() end,
  93. -- }
  94. -- { Shapes
  95. margins = 5,
  96. spacing = 5,
  97. shape = function(cr, width, height)
  98. return require("gears").shape.rounded_rect(cr,width,height,5)
  99. end,
  100. -- }
  101. },{__index = beautiful})
  102. }
  103. -- Subclasses
  104. awmtk.proto_style.container = awmtk.create_delta("container",{
  105. },awmtk.proto_style,awmtk.proto_style.base)
  106. awmtk.proto_style.button = awmtk.create_delta("button",{
  107. margins = 3
  108. },awmtk.proto_style,awmtk.proto_style.base)
  109. awmtk.proto_style.icon = awmtk.create_delta("icon",{
  110. margins = 1
  111. },awmtk.proto_style,awmtk.proto_style.base)
  112. awmtk.proto_style.textbox = awmtk.create_delta("textbox",{
  113. font = beautiful.font or "sans 8"
  114. }, awmtk.proto_style,awmtk.proto_style.base)
  115. awmtk.proto_style.separator = awmtk.create_delta("separator",{
  116. thickness = 1,
  117. color = beautiful.bg_focus,
  118. border_width = 0
  119. }, awmtk.proto_style,awmtk.proto_style.base)
  120. awmtk.proto_style.article = awmtk.create_delta("article", {
  121. icon_size = 16,
  122. small_font = beautiful.small_font or beautiful.font,
  123. font_align = "left",
  124. small_font_align = "left"
  125. }, awmtk.proto_style,awmtk.proto_style.base)
  126. awmtk.proto_style.popup = awmtk.create_delta("popup", {
  127. }, awmtk.proto_style,awmtk.proto_style.base)
  128. awmtk.proto_style.titlebar = awmtk.create_delta("titlebar", {
  129. margins = 1
  130. }, awmtk.proto_style,awmtk.proto_style.base)
  131. awmtk.proto_style.wibar = awmtk.create_delta("wibar", {
  132. margins = 1
  133. }, awmtk.proto_style,awmtk.proto_style.base)
  134. awmtk.proto_style.menu = awmtk.create_delta("menu", {
  135. margins = 1
  136. }, awmtk.proto_style,awmtk.proto_style.base)
  137. awmtk.proto_style.center = awmtk.create_delta("center", {
  138. margins = 1
  139. }, awmtk.proto_style,awmtk.proto_style.base)
  140. awmtk.proto_style.slider = awmtk.create_delta("slider", {
  141. margins = 1
  142. }, awmtk.proto_style,awmtk.proto_style.base)
  143. awmtk.proto_style.checkbox = awmtk.create_delta("checkbox", {
  144. }, awmtk.proto_style,awmtk.proto_style.base)
  145. -- }}}
  146. -- {{{ Generic templates
  147. awmtk.proto_templates = {
  148. -- Templates are built first using the given style, then applied to contents
  149. -- through returned function
  150. container = function(style)
  151. -- Container is practically any "box" that contains buttons, textboxes,
  152. -- and anything you want to put into the container. Do not confuse with
  153. -- popup - containers are designed to separate contents within a popup.
  154. return function(layout,options)
  155. return awmtk.merge({
  156. {
  157. layout,
  158. margins = style.container.margins,
  159. layout = wibox.container.margin
  160. },
  161. bgimage = style.container.bgimage_normal,
  162. bg = style.container.bg_normal,
  163. fg = style.container.fg_normal,
  164. shape = style.container.shape,
  165. shape_border_color = style.container.shape_border_color,
  166. shape_border_width = style.container.shape_border_width,
  167. widget = wibox.container.background
  168. },options or {})
  169. end
  170. end,
  171. button = function(style)
  172. -- Self explanatory. Notice that this does not bear any function -
  173. -- only the visual part of the button. By design, onpress and onrelease
  174. -- callbacks should be connected to button events for animations
  175. return function(layout,options)
  176. return awmtk.merge({
  177. {
  178. layout,
  179. margins = style.button.margins,
  180. layout = wibox.container.margin
  181. },
  182. bgimage = style.button.bgimage_normal,
  183. bg = style.button.bg_normal,
  184. fg = style.button.fg_normal,
  185. shape = style.button.shape,
  186. shape_border_color = style.button.shape_border_color,
  187. shape_border_width = style.button.shape_border_width,
  188. widget = wibox.container.background
  189. },options or {})
  190. end
  191. end,
  192. textbox = function(style)
  193. -- Nothing fancy here, but you can set per-widget fonts using beautiful.
  194. return function(options)
  195. return awmtk.merge({
  196. font = style.textbox.font,
  197. widget = wibox.widget.textbox,
  198. },options or {})
  199. end
  200. end,
  201. hseparator = function(style)
  202. -- Wow, i guess?
  203. return function(options)
  204. return awmtk.merge({
  205. widget = wibox.widget.separator,
  206. orientation = "horizontal",
  207. thickness = style.separator.thickness,
  208. color = style.separator.color,
  209. border_width = style.separator.border_width
  210. },options or {})
  211. end
  212. end,
  213. vseparator = function(style)
  214. -- I'm running out of comments
  215. return function(options)
  216. return awmtk.merge({
  217. widget = wibox.widget.separator,
  218. orientation = "vertical",
  219. thickness = style.separator.thickness,
  220. color = style.separator.color,
  221. border_width = style.separator.border_width
  222. },options or {})
  223. end
  224. end,
  225. article = function(style)
  226. -- Article is a template that combines 3 common pieces of a full item:
  227. -- Icon, name and description. Designed to be placed within a container
  228. -- or a button.
  229. return function(options)
  230. return awmtk.merge({
  231. (options.icon and {
  232. {
  233. {
  234. image = options.icon,
  235. id = options.icon_id,
  236. resize = options.resize,
  237. widget = wibox.widget.imagebox
  238. },
  239. strategy = "exact",
  240. height = options.icon_size or
  241. style.article.icon_size,
  242. width = options.icon_size or
  243. style.article.icon_size,
  244. widget = wibox.container.constraint
  245. },
  246. widget = wibox.container.place,
  247. valign = "center",
  248. halign = "center"
  249. }),
  250. {
  251. {
  252. markup = options.title or "",
  253. id = options.title_id,
  254. widget = wibox.widget.textbox,
  255. font = style.article.font,
  256. valign = style.article.title_valign or "center",
  257. align = style.article.title_align or "left"
  258. },
  259. (options.description and {
  260. markup = options.description or "",
  261. id = options.desc_id,
  262. widget = wibox.widget.textbox,
  263. font = style.article.small_font,
  264. valign = style.article.desc_valign or "center",
  265. align = style.article.desc_align or "left"
  266. }),
  267. spacing = style.article.spacing,
  268. layout = wibox.layout.flex.vertical
  269. },
  270. spacing = style.article.spacing,
  271. layout = wibox.layout.fixed.horizontal,
  272. }, options or {})
  273. end
  274. end,
  275. center = function(style)
  276. return function(layout,options)
  277. options = options or {}
  278. return awmtk.merge({
  279. {
  280. layout,
  281. strategy = "exact",
  282. height = options.height or
  283. style.center.height,
  284. width = options.width or
  285. style.center.width,
  286. widget = wibox.container.constraint
  287. },
  288. widget = wibox.container.place,
  289. valign = "center",
  290. halign = "center"
  291. },options or {})
  292. end
  293. end,
  294. popup = function(style)
  295. -- Popup is a distinct template designed to accomodate the "root" of
  296. -- a popup, allowing one to add titlebars to popups, for example.
  297. return function(widget,options)
  298. return awmtk.merge({
  299. widget = {
  300. widget,
  301. margins = style.popup.margins,
  302. layout = wibox.container.margin
  303. },
  304. bgimage = style.popup.bgimage_normal,
  305. shape = style.popup.shape,
  306. visible = false,
  307. ontop = true
  308. },options or {})
  309. end
  310. end,
  311. titlebar = function(style)
  312. -- Titlebar is a separate class specifically for window and popup
  313. -- titlebars. The decision to make it a separate class was due to
  314. -- the fact that much customization is done through default theme table
  315. return function(layout,options)
  316. -- If there's one thing that fascinates me, it's how much weird
  317. -- bugs i manage to uncover by some sort of miraculous accident.
  318. -- This one fixes a race condition in margins+(left/right/bottom/top) configuration scenario
  319. local margins = style.titlebar.margins
  320. if (style.titlebar.left or
  321. style.titlebar.right or
  322. style.titlebar.bottom or
  323. style.titlebar.top) then
  324. margins = nil
  325. end
  326. return awmtk.merge({
  327. layout,
  328. margins = margins,
  329. layout = wibox.container.margin,
  330. left = style.titlebar.left,
  331. right = style.titlebar.right,
  332. bottom = style.titlebar.bottom,
  333. top = style.titlebar.top
  334. },options or {})
  335. end
  336. end,
  337. wibar = function(style)
  338. -- Just you regular old wibar, but as a style template.
  339. return function(layout,options)
  340. local margins = style.wibar.margins
  341. if (style.wibar.left or
  342. style.wibar.right or
  343. style.wibar.bottom or
  344. style.wibar.top) then
  345. margins = nil
  346. end
  347. return awmtk.merge({
  348. layout,
  349. margins = margins,
  350. layout = wibox.container.margin,
  351. left = style.wibar.left,
  352. right = style.wibar.right,
  353. bottom = style.wibar.bottom,
  354. top = style.wibar.top
  355. },options or {})
  356. end
  357. end,
  358. slider = function(style)
  359. -- Slider widget but wired to work with the AWMTK2 namespace system
  360. return function(args)
  361. return awmtk.merge({
  362. handle_shape = style.slider.handle_shape or style.slider.shape,
  363. handle_color = style.slider.bg_normal,
  364. handle_margins = style.slider.handle_margins,
  365. handle_width = style.slider.handle_width,
  366. handle_border_color = style.slider.handle_border_color,
  367. handle_border_width = style.slider.handle_border_width,
  368. bar_shape = style.slider.bar_shape or style.slider.shape,
  369. bar_height = style.slider.bar_height,
  370. bar_color = style.slider.bg_focus,
  371. bar_margins = style.slider.bar_margins,
  372. bar_border_width = style.slider.bar_border_width,
  373. bar_border_color = style.slider.bar_border_color,
  374. forced_width = style.slider.width,
  375. forced_height = style.slider.height,
  376. widget = wibox.widget.slider
  377. },args or {})
  378. end
  379. end,
  380. checkbox = function(style)
  381. return function(args)
  382. return awmtk.merge({
  383. color = style.checkbox.bg_focus,
  384. padding = 2,
  385. shape = style.checkbox.shape,
  386. border_width = style.checkbox.shape_border_width,
  387. bg = style.checkbox.shape_border_color,
  388. widget = wibox.widget.checkbox
  389. },args or {})
  390. end
  391. end
  392. }
  393. -- Last but not least - we export a default template lib and default style.
  394. -- This is done in order to allow overriding default style behaviour from theme
  395. awmtk.default = awmtk.create_style("default",awmtk.proto_style,{})
  396. awmtk.templates = awmtk.create_template_lib("templates",awmtk.proto_templates,{})
  397. -- Generic styles for widgets that need them
  398. awmtk.generic = {}
  399. awmtk.generic.menu = awmtk.create_style("generic_menu",awmtk.default,{})
  400. awmtk.generic.button_list = awmtk.create_style("generic_button_list",awmtk.default,{})
  401. awmtk.generic.iconified_widget = awmtk.create_style("generic_iconified_widget",awmtk.default,{})
  402. awmtk.generic.status_widget = awmtk.create_style("generic_status_widget",awmtk.default,{})
  403. awmtk.generic.oneline_widget = awmtk.create_style("generic_oneline_widget",awmtk.default,{})
  404. awmtk.generic.composite_widget = awmtk.create_style("generic_composite_widget",awmtk.default,{})
  405. awmtk.generic.popup = awmtk.create_style("generic_popup",awmtk.default,{})
  406. -- }}}
  407. return awmtk