norcal 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -1
  3. data/bin/norcal +217 -123
  4. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: be5696e7434a165a2ef025c8152ddd359795d5cf6e1a42d6dae6a32c2f636e90
4
- data.tar.gz: fd6398b5697251b1c28c1c0b20c8fb3d99bc6b08980004612d37c94ea00e3469
3
+ metadata.gz: 628317b98eb4536e13c1199961ce51f89f246add68275897845fa08654060de1
4
+ data.tar.gz: 23ef85bb70d9342b372fb443b6ab26a3664c7b39b69ec479bbc54fe7a10c6423
5
5
  SHA512:
6
- metadata.gz: f8e7e3cf2c3e977ba03769fa6c215c18e2ff5fe13f7439b36ed18108f4db5d7ce6d12ef0cb9076ff88b70f923a30e2815b422d79a4da0de80a7de0d4a8192abb
7
- data.tar.gz: d2f1258004cd2b3b3a0fbc0a501fd94ef6bd0b5df63145747c899d68916718ffa9fcdb181d3ea46b7355b4672df1c8056f053b5988d2c7632f81a71093c2e42a
6
+ metadata.gz: a23ac49843b37ed383b08d6215a5a9f4f24416471539654053abd2574c4d4f5aa46e714d56d6f78a50a14a9e43d17652d08173d2cb08ddb6a584e8d2a6515432
7
+ data.tar.gz: d4392d35c14eda23aebf58669e627c908c754cda781cdba6d61f72e4dc1a9b135ed56c8ff387683bf4f3e2c919c512ed44c839aae7d2c6901f773f611e5281f7
data/README.md CHANGED
@@ -31,7 +31,7 @@ gem install norcal
31
31
  git clone https://github.com/baosen/norcal.git
32
32
  cd norcal
33
33
  gem build norcal.gemspec
34
- gem install norcal-1.0.0.gem
34
+ gem install norcal-1.2.0.gem
35
35
  ```
36
36
 
37
37
  ## Usage
@@ -52,6 +52,9 @@ norcal --light 2026 # light mode, specific year
52
52
  - Notable dates: royal birthdays, Samefolkets dag, Morsdag, Farsdag, solverv, sommertid, and more
53
53
  - Today highlighted with yellow background
54
54
  - Dark mode (default) and light mode, with toggle button
55
+ - Zoom in/out (`+`/`–` buttons, Ctrl+scroll, Ctrl++/Ctrl+-)
56
+ - Auto-fit to screen height on startup, with `fit` button
57
+ - Scrollbar for zoomed-in views
55
58
 
56
59
  ## License
57
60
 
data/bin/norcal CHANGED
@@ -66,7 +66,7 @@ def red_days(year)
66
66
  e - 2 => "Langfredag",
67
67
  e => "1. påskedag",
68
68
  e + 1 => "2. påskedag",
69
- Date.new(year, 5, 1) => "Off. høgtidsdag",
69
+ Date.new(year, 5, 1) => "Arbeidernes dag",
70
70
  e + 39 => "Kr. Himmelfartsdag",
71
71
  Date.new(year, 5, 17) => "Grunnlovsdag",
72
72
  e + 49 => "1. pinsedag",
@@ -102,7 +102,7 @@ def notable_dates(year)
102
102
  [e - 2, "Langfredag", true],
103
103
  [e, "1. påskedag", true],
104
104
  [e + 1, "2. påskedag", true],
105
- [Date.new(year, 5, 1), "Off. høgtidsdag", true],
105
+ [Date.new(year, 5, 1), "Arbeidernes dag", true],
106
106
  [Date.new(year, 5, 8), "Frigjøringsdag 1945", false],
107
107
  [e + 39, "Kr. Himmelfartsdag", true],
108
108
  [Date.new(year, 5, 17), "Grunnlovsdag 1814", true],
@@ -148,72 +148,108 @@ THEME = {
148
148
  # Parse arguments: optional --light flag and optional year (dark is default)
149
149
  $dark = ARGV.delete('--light') ? false : true
150
150
  $year = (ARGV[0] || Date.today.year).to_i
151
+ $zoom = 0
151
152
 
152
153
  def theme
153
154
  THEME[$dark ? :dark : :light]
154
155
  end
155
156
 
156
- root = TkRoot.new do
157
+ FONT = 'Noto Serif'
158
+
159
+ def make_fonts
160
+ z = $zoom
161
+ {
162
+ title: TkFont.new(family: FONT, size: 22 + z, weight: 'bold'),
163
+ mheader: TkFont.new(family: FONT, size: 13 + z, weight: 'bold'),
164
+ cal: TkFont.new(family: FONT, size: 12 + z),
165
+ cal_bold: TkFont.new(family: FONT, size: 12 + z, weight: 'bold'),
166
+ note: TkFont.new(family: FONT, size: 11 + z),
167
+ note_b: TkFont.new(family: FONT, size: 11 + z, weight: 'bold'),
168
+ note_d: TkFont.new(family: FONT, size: 11 + z),
169
+ btn: TkFont.new(family: FONT, size: 9 + z),
170
+ }
171
+ end
172
+
173
+ $root = TkRoot.new do
157
174
  title "norcal"
158
175
  end
159
176
 
160
- # Fonts
161
- ft_title = TkFont.new(family: 'Noto Serif', size: 22, weight: 'bold')
162
- ft_mheader = TkFont.new(family: 'Noto Serif', size: 13, weight: 'bold')
163
- ft_cal = TkFont.new(family: 'Noto Serif', size: 12)
164
- ft_cal_bold = TkFont.new(family: 'Noto Serif', size: 12, weight: 'bold')
165
- ft_note = TkFont.new(family: 'Noto Serif', size: 11)
166
- ft_note_b = TkFont.new(family: 'Noto Serif', size: 11, weight: 'bold')
167
- ft_note_d = TkFont.new(family: 'Noto Serif', size: 11)
168
- ft_toggle = TkFont.new(family: 'Noto Serif', size: 9)
177
+ # -- Widget tracking for in-place updates --------------------------------------
169
178
 
170
- # -- Calendar content ----------------------------------------------------------
179
+ # All trackable widgets, grouped by update type.
180
+ # Labels store {w: widget, fg: theme_key, bg: theme_key, font: font_key}.
181
+ # Buttons store {w: widget, fg: theme_key, text_key: theme_key or nil, text: static}.
182
+ $w = { bg: [], border: [], sep: [], labels: [], texts: [], buttons: [] }
171
183
 
172
- def render_month(parent, year, month, holidays, fonts)
173
- ft_mheader, ft_cal, ft_cal_bold = fonts
184
+ # Apply current theme + zoom to all tracked widgets (no widget recreation).
185
+ def restyle
174
186
  t = theme
187
+ f = make_fonts
188
+
189
+ $root.configure(background: t[:bg])
190
+ $canvas.configure(background: t[:bg])
191
+ $scrollbar.configure(background: t[:bg], troughcolor: t[:bg])
192
+ $root.title = "Kalender #{$year}"
175
193
 
194
+ $w[:bg].each { |w| w.configure(background: t[:bg]) }
195
+ $w[:border].each { |w| w.configure(background: t[:bg], highlightbackground: t[:border]) }
196
+ $w[:sep].each { |w| w.configure(background: t[:sep]) }
197
+
198
+ $w[:labels].each do |e|
199
+ e[:w].configure(foreground: t[e[:fg]], background: t[e[:bg]], font: f[e[:font]])
200
+ end
201
+
202
+ $w[:texts].each do |tw|
203
+ tab = [65 + $zoom * 4, 40].max
204
+ tw.configure(background: t[:bg], font: f[:note], tabs: tab.to_s)
205
+ tw.tag_configure('dt', foreground: t[:fg], font: f[:note_b])
206
+ tw.tag_configure('dtr', foreground: t[:red], font: f[:note_b])
207
+ tw.tag_configure('desc', foreground: t[:desc_fg], font: f[:note_d])
208
+ end
209
+
210
+ $w[:buttons].each do |e|
211
+ text = e[:text_key] ? t[e[:text_key]] : e[:text]
212
+ e[:w].configure(text: text, font: f[:btn], foreground: t[e[:fg]],
213
+ background: t[:bg], activebackground: t[:bg], activeforeground: t[:fg])
214
+ end
215
+ end
216
+
217
+ # -- Build calendar (one-time per year) ----------------------------------------
218
+
219
+ def build_month(parent, year, month, holidays)
176
220
  first = Date.new(year, month, 1)
177
221
  last_day = Date.new(year, month, -1)
178
222
  monday = first - (first.cwday - 1)
179
223
  today = Date.today
180
224
 
181
- outer = TkFrame.new(parent) {
182
- borderwidth 1; relief 'solid'; background t[:bg]
183
- highlightbackground t[:border]; highlightthickness 0
184
- }
225
+ outer = TkFrame.new(parent) { borderwidth 1; relief 'solid'; highlightthickness 0 }
226
+ $w[:border] << outer
185
227
 
186
- grid = TkFrame.new(outer) { background t[:bg]; padx 6; pady 4 }
228
+ grid = TkFrame.new(outer) { padx 6; pady 4 }
229
+ $w[:bg] << grid
187
230
  grid.pack
188
231
 
189
- # Month name header
190
- TkLabel.new(grid) {
191
- text MONTHS_NO[month - 1]; font ft_mheader; foreground t[:fg]; background t[:bg]
192
- }.grid(row: 0, column: 0, columnspan: 8, pady: [0, 2])
232
+ hdr = TkLabel.new(grid) { text MONTHS_NO[month - 1] }
233
+ $w[:labels] << { w: hdr, fg: :fg, bg: :bg, font: :mheader }
234
+ hdr.grid(row: 0, column: 0, columnspan: 8, pady: [0, 2])
193
235
 
194
- # Day-name headers
195
- TkLabel.new(grid) {
196
- text 'Uke'; font ft_cal; foreground t[:dkgray]; background t[:bg]
197
- }.grid(row: 1, column: 0, sticky: 'e', padx: [0, 4])
236
+ uke = TkLabel.new(grid) { text 'Uke' }
237
+ $w[:labels] << { w: uke, fg: :dkgray, bg: :bg, font: :cal }
238
+ uke.grid(row: 1, column: 0, sticky: 'e', padx: [0, 4])
198
239
 
199
240
  DAYS_NO.each_with_index do |d, i|
200
- fg = case i
201
- when 5 then t[:gray]
202
- when 6 then t[:red]
203
- else t[:fg]
204
- end
205
- TkLabel.new(grid) {
206
- text d; font ft_cal_bold; foreground fg; background t[:bg]
207
- }.grid(row: 1, column: i + 1, sticky: 'e')
241
+ fg_key = case i when 5 then :gray when 6 then :red else :fg end
242
+ lbl = TkLabel.new(grid) { text d }
243
+ $w[:labels] << { w: lbl, fg: fg_key, bg: :bg, font: :cal_bold }
244
+ lbl.grid(row: 1, column: i + 1, sticky: 'e')
208
245
  end
209
246
 
210
- # Week rows
211
247
  row = 2
212
248
  cur = monday
213
249
  while cur <= last_day
214
- TkLabel.new(grid) {
215
- text cur.cweek.to_s; font ft_cal; foreground t[:dkgray]; background t[:bg]
216
- }.grid(row: row, column: 0, sticky: 'e', padx: [0, 4])
250
+ wk = TkLabel.new(grid) { text cur.cweek.to_s }
251
+ $w[:labels] << { w: wk, fg: :dkgray, bg: :bg, font: :cal }
252
+ wk.grid(row: row, column: 0, sticky: 'e', padx: [0, 4])
217
253
 
218
254
  7.times do |i|
219
255
  day = cur + i
@@ -221,149 +257,207 @@ def render_month(parent, year, month, holidays, fonts)
221
257
  is_red = day.cwday == 7 || holidays.key?(day)
222
258
  is_sat = day.cwday == 6 && !holidays.key?(day)
223
259
  is_today = day == today
224
- fg = if is_red then t[:red]
225
- elsif is_sat then t[:gray]
226
- else t[:fg]
227
- end
228
- TkLabel.new(grid) {
229
- text day.day.to_s
230
- font(is_today ? ft_cal_bold : ft_cal)
231
- foreground fg
232
- background(is_today ? t[:today_bg] : t[:bg])
233
- }.grid(row: row, column: i + 1, sticky: 'e')
260
+ fg_key = is_red ? :red : (is_sat ? :gray : :fg)
261
+ bg_key = is_today ? :today_bg : :bg
262
+ font_key = is_today ? :cal_bold : :cal
263
+
264
+ lbl = TkLabel.new(grid) { text day.day.to_s }
265
+ $w[:labels] << { w: lbl, fg: fg_key, bg: bg_key, font: font_key }
266
+ lbl.grid(row: row, column: i + 1, sticky: 'e')
234
267
  end
235
268
  end
236
269
  row += 1
237
270
  cur += 7
238
271
  end
239
272
 
240
- # Pad empty rows so all months have the same height (max 6 week rows)
241
273
  while row < 8
242
- TkLabel.new(grid) { text ' '; font ft_cal; background t[:bg] }
243
- .grid(row: row, column: 0)
274
+ pad = TkLabel.new(grid) { text ' ' }
275
+ $w[:labels] << { w: pad, fg: :fg, bg: :bg, font: :cal }
276
+ pad.grid(row: row, column: 0)
244
277
  row += 1
245
278
  end
246
279
 
247
- # Uniform column widths
248
280
  (1..7).each { |c| grid.grid_columnconfigure(c, uniform: 'day', minsize: 22) }
249
-
250
281
  outer
251
282
  end
252
283
 
253
- def render_notable(parent, year, fonts)
254
- ft_note, ft_note_b, ft_note_d = fonts
255
- t = theme
284
+ def build_notable(parent, year)
256
285
  dates = notable_dates(year)
257
-
258
- # Split into 3 roughly-equal columns
259
286
  third = (dates.size / 3.0).ceil
260
- cols = dates.each_slice(third).to_a
287
+ cols = dates.each_slice(third).to_a
261
288
 
262
- outer = TkFrame.new(parent) {
263
- borderwidth 1; relief 'solid'; background t[:bg]
264
- highlightbackground t[:border]; highlightthickness 0
265
- }
289
+ outer = TkFrame.new(parent) { borderwidth 1; relief 'solid'; highlightthickness 0 }
290
+ $w[:border] << outer
266
291
 
267
- inner = TkFrame.new(outer) { background t[:bg] }
292
+ inner = TkFrame.new(outer)
293
+ $w[:bg] << inner
268
294
  inner.pack(padx: 5, pady: 5, fill: 'both')
269
295
 
270
296
  cols.each_with_index do |entries, ci|
271
297
  tw = TkText.new(inner) {
272
298
  width 1; height(entries.size + 4)
273
- font ft_note; borderwidth 0; highlightthickness 0
274
- wrap 'word'; background t[:bg]; padx 3; pady 2
275
- cursor ''; insertwidth 0
276
- tabs '65'
299
+ borderwidth 0; highlightthickness 0
300
+ wrap 'word'; padx 3; pady 2; cursor ''; insertwidth 0
277
301
  }
278
- tw.tag_configure('dt', foreground: t[:fg], font: ft_note_b)
279
- tw.tag_configure('dtr', foreground: t[:red], font: ft_note_b)
280
- tw.tag_configure('desc', foreground: t[:desc_fg], font: ft_note_d)
302
+ $w[:texts] << tw
281
303
 
282
304
  entries.each_with_index do |(date, desc, is_red), i|
283
305
  dtag = is_red ? 'dtr' : 'dt'
284
- date_str = "#{date.day}. #{MABBR_NO[date.month - 1]}"
285
- tw.insert('end', date_str, dtag)
306
+ tw.insert('end', "#{date.day}. #{MABBR_NO[date.month - 1]}", dtag)
286
307
  tw.insert('end', "\t")
287
308
  tw.insert('end', desc, 'desc')
288
309
  tw.insert('end', "\n") unless i == entries.size - 1
289
310
  end
290
-
291
311
  tw.state 'disabled'
292
312
  tw.grid(row: 0, column: ci * 2, sticky: 'nsew', padx: [0, 2])
293
313
  inner.grid_columnconfigure(ci * 2, weight: 1, uniform: 'notecol')
294
314
  inner.grid_rowconfigure(0, weight: 1)
295
315
 
296
- # vertical separator between columns (except after last)
297
316
  if ci < cols.size - 1
298
- sep = TkFrame.new(inner) { background t[:sep]; width 1 }
317
+ sep = TkFrame.new(inner) { width 1 }
318
+ $w[:sep] << sep
299
319
  sep.grid(row: 0, column: ci * 2 + 1, sticky: 'ns', padx: 4)
300
320
  end
301
321
  end
302
-
303
322
  outer
304
323
  end
305
324
 
306
- def build_calendar(parent, year, fonts)
307
- ft_mheader, ft_cal, ft_cal_bold, ft_note, ft_note_b, ft_note_d = fonts
308
- t = theme
325
+ def build_buttons(parent)
326
+ btn_bar = TkFrame.new(parent)
327
+ $w[:bg] << btn_bar
328
+ btn_bar.grid(row: 5, column: 0, columnspan: 3, pady: [4, 0])
329
+
330
+ b1 = TkButton.new(btn_bar) { relief 'flat'; borderwidth 0; command { $dark = !$dark; restyle } }
331
+ $w[:buttons] << { w: b1, fg: :dkgray, text_key: :toggle_label, text: nil }
332
+ b1.pack(side: 'left', padx: 4)
333
+
334
+ b2 = TkButton.new(btn_bar) { relief 'flat'; borderwidth 0; command { $zoom += 1; restyle } }
335
+ $w[:buttons] << { w: b2, fg: :dkgray, text_key: nil, text: '+' }
336
+ b2.pack(side: 'left', padx: 2)
337
+
338
+ b3 = TkButton.new(btn_bar) { relief 'flat'; borderwidth 0; command { $zoom -= 1 if $zoom > -8; restyle } }
339
+ $w[:buttons] << { w: b3, fg: :dkgray, text_key: nil, text: "\u2013" }
340
+ b3.pack(side: 'left', padx: 2)
341
+
342
+ b4 = TkButton.new(btn_bar) { relief 'flat'; borderwidth 0; command { $fit.call(false) } }
343
+ $w[:buttons] << { w: b4, fg: :dkgray, text_key: nil, text: 'fit' }
344
+ b4.pack(side: 'left', padx: 2)
345
+ end
346
+
347
+ def build_all(year)
348
+ $w.each_value(&:clear)
349
+ $inner_frame&.destroy
350
+
309
351
  holidays = red_days(year)
310
352
 
311
- frame = TkFrame.new(parent) { background t[:bg] }
353
+ $inner_frame = TkFrame.new($canvas)
354
+ $w[:bg] << $inner_frame
355
+
356
+ title = TkLabel.new($inner_frame) { text year.to_s }
357
+ $w[:labels] << { w: title, fg: :title_fg, bg: :bg, font: :title }
358
+ title.pack(pady: [8, 2])
312
359
 
313
- # Single grid for months and notable dates
314
- grid_f = TkFrame.new(frame) { background t[:bg] }
315
- grid_f.pack(padx: 10, pady: [2, 8])
360
+ frame = TkFrame.new($inner_frame)
361
+ $w[:bg] << frame
362
+ frame.pack(padx: 10, pady: [2, 8])
363
+
364
+ grid_f = TkFrame.new(frame)
365
+ $w[:bg] << grid_f
366
+ grid_f.pack
316
367
 
317
368
  12.times do |idx|
318
- m_frame = render_month(grid_f, year, idx + 1, holidays,
319
- [ft_mheader, ft_cal, ft_cal_bold])
320
- m_frame.grid(row: idx / 3, column: idx % 3, padx: 3, pady: 3, sticky: 'nsew')
369
+ build_month(grid_f, year, idx + 1, holidays)
370
+ .grid(row: idx / 3, column: idx % 3, padx: 3, pady: 3, sticky: 'nsew')
321
371
  end
322
372
 
323
- # Notable dates in row 4, spanning all 3 month columns
324
- note_f = render_notable(grid_f, year, [ft_note, ft_note_b, ft_note_d])
325
- note_f.grid(row: 4, column: 0, columnspan: 3, padx: 3, pady: [4, 0], sticky: 'ew')
326
-
327
- # Toggle button below notable dates
328
- TkButton.new(grid_f) {
329
- text t[:toggle_label]; font fonts[5] # ft_note_d
330
- relief 'flat'; borderwidth 0
331
- foreground t[:dkgray]; background t[:bg]
332
- activebackground t[:bg]; activeforeground t[:fg]
333
- command { $dark = !$dark; $rebuild&.call }
334
- }.grid(row: 5, column: 0, columnspan: 3, pady: [4, 0])
373
+ build_notable(grid_f, year)
374
+ .grid(row: 4, column: 0, columnspan: 3, padx: 3, pady: [4, 0], sticky: 'ew')
335
375
 
376
+ build_buttons(grid_f)
336
377
  3.times { |c| grid_f.grid_columnconfigure(c, weight: 1) }
337
378
 
338
- frame
339
- end
379
+ # Embed in canvas
380
+ $canvas.delete('all')
381
+ $canvas_win = $canvas.create(:window, 0, 0, window: $inner_frame, anchor: 'nw')
340
382
 
341
- # -- Title ---------------------------------------------------------------------
383
+ center = proc {
384
+ cw = $canvas.winfo_width; ch = $canvas.winfo_height
385
+ fw = $inner_frame.winfo_reqwidth; fh = $inner_frame.winfo_reqheight
386
+ $canvas.coords($canvas_win, [(cw - fw) / 2, 0].max, [(ch - fh) / 2, 0].max)
387
+ $canvas.configure(scrollregion: "0 0 #{[cw, fw].max} #{[ch, fh].max}")
388
+ }
389
+ $inner_frame.bind('Configure', center)
390
+ $canvas.bind('Configure', center)
342
391
 
343
- $top = TkFrame.new(root) { background theme[:bg] }
344
- $top.pack(fill: 'x', pady: [8, 2])
392
+ restyle
393
+ end
345
394
 
346
- $title_lbl = TkLabel.new($top) {
347
- text $year.to_s; font ft_title; foreground theme[:title_fg]; background theme[:bg]
395
+ # -- Scrollable wrapper --------------------------------------------------------
396
+
397
+ $scrollbar = TkScrollbar.new($root)
398
+ $canvas = TkCanvas.new($root) { highlightthickness 0; borderwidth 0 }
399
+ $canvas.configure(yscrollcommand: proc { |*a| $scrollbar.set(*a) })
400
+ $scrollbar.command(proc { |*a| $canvas.yview(*a) })
401
+ $scrollbar.pack(side: 'right', fill: 'y')
402
+ $canvas.pack(side: 'left', fill: 'both', expand: true)
403
+
404
+ # Scrolling
405
+ $root.bind('MouseWheel') { |e| $canvas.yview_scroll(-e.delta / 120, 'units') }
406
+ $root.bind('Button-4') { $canvas.yview_scroll(-3, 'units') }
407
+ $root.bind('Button-5') { $canvas.yview_scroll(3, 'units') }
408
+
409
+ # Keyboard zoom
410
+ $root.bind('Control-plus') { $zoom += 1; restyle }
411
+ $root.bind('Control-equal') { $zoom += 1; restyle }
412
+ $root.bind('Control-minus') { $zoom -= 1 if $zoom > -8; restyle }
413
+
414
+ # Ctrl+mouse wheel zoom
415
+ $root.bind('Control-MouseWheel') { |e|
416
+ if e.delta > 0 then $zoom += 1 else $zoom -= 1 if $zoom > -8 end
417
+ restyle
348
418
  }
349
- $title_lbl.pack
419
+ $root.bind('Control-Button-4') { $zoom += 1; restyle }
420
+ $root.bind('Control-Button-5') { $zoom -= 1 if $zoom > -8; restyle }
350
421
 
351
- # -- Build & rebuild -----------------------------------------------------------
422
+ # -- Fit to window -------------------------------------------------------------
352
423
 
353
- all_fonts = [ft_mheader, ft_cal, ft_cal_bold, ft_note, ft_note_b, ft_note_d]
354
- $content = nil
355
- $rebuild = nil
424
+ $fit = proc { |resize_window|
425
+ target_h = resize_window ? $root.winfo_screenheight - 80 : $root.winfo_height
426
+ cur_h = $inner_frame.winfo_reqheight.to_f
427
+ base_avg = 13.0
356
428
 
357
- $rebuild = proc {
358
- t = theme
359
- $content&.destroy
360
- root.configure(background: t[:bg])
361
- $top.configure(background: t[:bg])
362
- $title_lbl.configure(foreground: t[:title_fg], background: t[:bg])
363
- root.title = "norcal - #{$year}"
364
- $content = build_calendar(root, $year, all_fonts)
365
- $content.pack(fill: 'both', expand: true)
429
+ if cur_h > 0 && target_h > 0
430
+ cur_font = base_avg + $zoom
431
+ target_font = cur_font * (target_h / cur_h)
432
+ $zoom = (target_font - base_avg).floor
433
+ $zoom = [$zoom, -8].max
434
+ end
435
+
436
+ restyle
437
+ Tk.update_idletasks
438
+
439
+ if $inner_frame.winfo_reqheight > target_h
440
+ $zoom -= 1
441
+ restyle
442
+ Tk.update_idletasks
443
+ end
444
+
445
+ if resize_window
446
+ cw = $inner_frame.winfo_reqwidth + 20
447
+ ch = $inner_frame.winfo_reqheight
448
+ sw = $root.winfo_screenwidth
449
+ mh = $root.winfo_screenheight - 50
450
+ w = [cw, sw].min; h = [ch, mh].min
451
+ $root.geometry("#{w}x#{h}+#{(sw - w) / 2}+0")
452
+ end
366
453
  }
367
454
 
368
- $rebuild.call
455
+ # -- Startup -------------------------------------------------------------------
456
+
457
+ $root.withdraw
458
+ build_all($year)
459
+ Tk.update_idletasks
460
+ $fit.call(true)
461
+ $root.deiconify
462
+
369
463
  Tk.mainloop
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: norcal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - baosen