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.

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