-
Notifications
You must be signed in to change notification settings - Fork 15
/
Scrolling_Window_Demo.xml
550 lines (423 loc) · 15.7 KB
/
Scrolling_Window_Demo.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<muclient>
<plugin
name="Scrolling_Window"
author="Nick Gammon"
id="a160a0dc029b28fc970a935d"
language="Lua"
purpose="Implements scrolling text window"
date_written="2017-01-30 15:34"
date_modified="2017-02-01 14:51"
requires="4.94"
version="2.2"
save_state="y"
>
<description trim="y">
Usage
-----
require "serialize" -- needed to serialize table to string
-- plugin ID needed to call this plugin
ScrollingPlugin = "a160a0dc029b28fc970a935d"
-- example sizes (pixels)
width = 500
height = 300
-- changes scroll window width and height (default 400 x 200)
CallPlugin (ScrollingPlugin, "SetSize" , width, height)
-- set the window title (if an empty string, no title is shown)
CallPlugin (ScrollingPlugin, "SetTitle", "Example title")
-- example table of lines
lines = { }
for i = 1, 300 do
table.insert (lines, string.format ("Line %03i ", i))
end -- for
-- sets the window text (a table of lines)
CallPlugin (ScrollingPlugin, "SetText", serialize.save_simple (lines))
-- add a new line to the end of the table of lines
-- if "wrap" is true then long lines are split at the closest space at
-- the RH side of the window (possibly inserting multiple lines) otherwise
-- the line is inserted "as is" possibly truncating it
CallPlugin (ScrollingPlugin, "AddLine", "New line", wrap)
-- remove "count" lines from the start of the table of lines
CallPlugin (ScrollingPlugin, "RemoveLines", count)
-- find number of lines in the lines table
rc, count = CallPlugin (ScrollingPlugin, "GetLineCount")
-- sets the text colour (RGB values)
CallPlugin (ScrollingPlugin, "SetTextColour", foreground, background)
-- sets the title bar colour (RGB values)
CallPlugin (ScrollingPlugin, "SetTitleColour", foreground, background)
-- show the window
CallPlugin (ScrollingPlugin, "Show")
-- hide the window
CallPlugin (ScrollingPlugin, "Hide")
-- set the scroll position
CallPlugin (ScrollingPlugin, "SetScrollPosition", position)
-- get the scroll position
rc, pos = CallPlugin (ScrollingPlugin, "GetScrollPosition")
-- sets the window font (default 9 point Lucida Console)
CallPlugin (ScrollingPlugin, "SetFont", size, name)
-- sets whether to use Unicode or not (default false)
CallPlugin (ScrollingPlugin, "Unicode", true)
-- RH-click on the window to get a "Copy" and "Font" menu
</description>
</plugin>
<!-- Script -->
<script>
<![CDATA[
require "movewindow"
-- configuration
-- window size in pixels
windowWidth = 400
windowHeight = 200
-- font
fontSize = 9
fontName = "Lucida Console"
-- Unicode? (UTF-8)
Utf8 = false
-- where to put the window
WINDOW_POSITION = miniwin.pos_top_right
-- default colours
windowTextColour = ColourNameToRGB ("black")
windowBackgroundColour = ColourNameToRGB ("khaki")
windowTitleTextColour = ColourNameToRGB ("white")
windowTitleBackgroundColour = ColourNameToRGB ("darkgoldenrod")
-- offset of text from edge
TEXT_INSET = 5
SCROLL_BAR_SIZE = 20
SCROLL_THUMB_HOTSPOT = "thumb"
SCROLL_WHEEL_HOTSPOT = "ScrollWheelHotspot"
FONT_ID = "f"
lines = { }
title = "" -- default empty title
scrollPos = 0 -- where scroll bar is (pixels)
-- display one line
function Display_Line (line, text)
-- don't both drawing if it won't be visible
if top + fontHeight >= 0 and top <= windowHeight then
WindowText (win, FONT_ID, text, TEXT_INSET, top, windowWidth - TEXT_INSET, 0, windowTextColour, Utf8)
end -- if visible
top = top + fontHeight
end -- Display_Line
function ShowLines ()
if #lines == 0 and #title == 0 then
WindowShow (win, false) -- hide it
return -- all done
end -- nothing to show
-- if no title don't use the space for it
if #title == 0 then
titleBoxHeight = 0
else
titleBoxHeight = fontHeight + TEXT_INSET * 2
end -- if
-- recalculate how much room for text
windowClientHeight = windowHeight - titleBoxHeight
-- how many pixels are in the scroll bar (apart from the thumb)
scrollBarPixels = windowClientHeight - SCROLL_BAR_SIZE
scrollPos = math.max (scrollPos, titleBoxHeight) -- don't go above top of scroll bar
scrollPos = math.min (scrollPos, windowHeight - SCROLL_BAR_SIZE) -- don't go below bottom of scroll bar
-- free pixels are all in the scroll bar except the thumb
local amountThrough = (scrollPos - titleBoxHeight) / scrollBarPixels
top = - ((#lines * fontHeight) - windowClientHeight)
top = top * amountThrough
top = top + titleBoxHeight -- allow for title
-- blank existing window contents
WindowRectOp (win, miniwin.rect_fill, 0, 0, 0, 0, windowBackgroundColour)
-- display all lines
for k, v in ipairs (lines) do
Display_Line (k, v)
end -- for
-- draw title
if #title > 0 then
WindowRectOp (win, miniwin.rect_fill, 0, 0, 0, titleBoxHeight, windowTitleBackgroundColour)
WindowText (win, FONT_ID, title, TEXT_INSET, TEXT_INSET, windowWidth - TEXT_INSET, 0, windowTitleTextColour)
end -- if having a title
-- if more lines than will fit, show a scroll bar
if #lines > maxLines then
WindowRectOp (win, miniwin.rect_fill, windowWidth - SCROLL_BAR_SIZE, titleBoxHeight, 0, 0, GetSysColor (0))
-- now draw the thumb
local scrollBarLeft = windowWidth - SCROLL_BAR_SIZE
local scrollBarTop = scrollPos
local scrollBarRight = 0
local scrollBarBottom = scrollBarTop + SCROLL_BAR_SIZE
WindowRectOp (win, miniwin.rect_draw_edge,
scrollBarLeft, scrollBarTop, scrollBarRight, scrollBarBottom,
miniwin.rect_edge_raised,
miniwin.rect_edge_at_all +
miniwin.rect_option_softer_buttons)
WindowMoveHotspot(win, SCROLL_THUMB_HOTSPOT, scrollBarLeft, scrollBarTop, scrollBarRight, scrollBarBottom)
end -- of needing a scroll bar
-- force window redisplay
WindowShow (win, true) -- show it
end -- end ShowLines
-- hide window on removal
function OnPluginClose ()
WindowShow (win, false) -- hide it
end -- OnPluginClose
-- hide window on disable
function OnPluginDisable ()
WindowShow (win, false) -- hide it
end -- OnPluginDisable
-- show window on enable
function OnPluginEnable ()
if #lines > 0 or #title > 0 then
WindowShow (win, true) -- show it
end -- if something to show
end -- OnPluginEnable
function MouseDown ()
-- get location of cursor relative to the hotspot
hotSpotAdjust = WindowInfo (win, 15) - WindowHotspotInfo (win, SCROLL_THUMB_HOTSPOT, 2)
end -- MouseDown
function dragMove ()
-- get location of cursor relative to the window
local posy = WindowInfo (win, 18) - WindowInfo (win, 11) - hotSpotAdjust
scrollPos = posy
-- redisplay the window
ShowLines ()
end -- dragMove
function wheelMove (flags, hotspot_id)
if bit.band (flags, miniwin.wheel_scroll_back) ~= 0 then
-- wheel scrolled down (towards you)
scrollPos = scrollPos + 1
else
-- wheel scrolled up (away from you)
scrollPos = scrollPos - 1
end -- if
-- redisplay the window
ShowLines ()
end -- wheel_move
function MouseUpInClient (flags, hotspotID)
-- ignore if not RH mouse click
if bit.band (flags, miniwin.hotspot_got_rh_mouse) == 0 then
return
end -- if
local result = WindowMenu (win,
WindowInfo (win, 14), -- x
WindowInfo (win, 15), -- y
"! Copy | Font ...")
if result == "1" then -- Copy
-- concatenate lines together with carriage-return/newline
-- add final carriage-return/newline
-- put onto clipboard
SetClipboard(table.concat (lines, "\r\n") .. "\r\n")
elseif result == "2" then -- Font
wanted_font = utils.fontpicker (fontName, fontSize, windowTextColour)
if wanted_font then
fontSize = wanted_font.size
fontName = wanted_font.name
windowTextColour = wanted_font.colour
SetVariable ("FontSize", fontSize)
SetVariable ("FontName", fontName)
SetVariable ("FontColour", windowTextColour)
OnPluginInstall () -- set everything up again
end -- if font chosen
end -- if
end -- MouseUpInClient
function OnPluginInstall ()
-- startup stuff
win = "scroll_" .. GetPluginID () -- get a unique name
-- get the font information they may have saved last time
fontSize = tonumber (GetVariable ("FontSize")) or fontSize
fontName = GetVariable ("FontName") or fontName
windowTextColour = tonumber (GetVariable ("FontColour")) or windowTextColour
windowinfo = movewindow.install (win, WINDOW_POSITION, 0) -- default position / flags
-- make the window
WindowCreate (win, windowinfo.window_left,
windowinfo.window_top,
windowWidth,
windowHeight,
windowinfo.window_mode,
windowinfo.window_flags,
windowBackgroundColour) -- create window
-- grab a font
WindowFont (win, FONT_ID, fontName, fontSize) -- define font
-- work out how high it is
fontHeight = WindowFontInfo (win, FONT_ID, 1) -- height of the font
-- how big the title box is
titleBoxHeight = fontHeight + TEXT_INSET * 2
-- useable area for text
windowClientHeight = windowHeight - titleBoxHeight
movewindow.add_drag_handler (win, 0, 0, 0, titleBoxHeight, miniwin.cursor_both_arrow)
-- work out how many lines will fit
maxLines = math.floor (windowClientHeight / fontHeight)
-- scroll bar thumb
WindowAddHotspot(win, SCROLL_THUMB_HOTSPOT,
0, 0, 0, 0, -- position will be changed when we draw the window anyway
"", -- MouseOver
"", -- CancelMouseOver
"MouseDown",
"", -- CancelMouseDown
"", -- MouseUp
"", -- TooltipText
miniwin.cursor_arrow,
0) -- Flags
WindowDragHandler(win, SCROLL_THUMB_HOTSPOT, "dragMove", "", 0)
WindowAddHotspot(win, SCROLL_WHEEL_HOTSPOT,
0, titleBoxHeight, windowWidth - SCROLL_BAR_SIZE, 0,
"", -- MouseOver
"", -- CancelMouseOver
"", -- MouseDown
"", -- CancelMouseDown
"MouseUpInClient", -- MouseUp
"", -- TooltipText
miniwin.cursor_arrow,
0) -- Flags
WindowScrollwheelHandler(win, SCROLL_WHEEL_HOTSPOT, "wheelMove");
ShowLines ()
end -- OnPluginInstall
function OnPluginSaveState ()
-- save window current location for next time
movewindow.save_state (win)
SetVariable ("FontSize", fontSize)
SetVariable ("FontName", fontName)
SetVariable ("FontColour", windowTextColour)
end -- function OnPluginSaveState
-- ############################# CALLBACKS ########################
function SetSize (width, height)
assert (type (width) == "number", "In SetSize, width is not numeric")
assert (type (height) == "number", "In SetSize, height is not numeric")
windowWidth = width
windowHeight = height
OnPluginInstall () -- set everything up again
end -- SetSize
function SetText (text)
assert (type (text) == "string", "In SetText, text is not a string")
local t = {} -- put into local table
setfenv (assert (loadstring ("lines = " .. text),
"In SetText, text is not serialized correctly"), t) ()
assert (type (t.lines) == "table", "In SetText, text does not contain a table")
lines = t.lines -- copy to our global variable
-- display new lines
ShowLines ()
end -- of SetText
function AddLine (text, wrap)
assert (type (text) == "string", "In AddLine, text is not a string")
text = string.gsub (text, "\r", "") -- get rid of carriage-returns
-- honour newlines however
if not wrap then
local t = utils.split (text, "\n")
for _, line in ipairs (t) do
table.insert (lines, line) -- insert into existing text
end -- for
ShowLines ()
return
end -- not wrapping
local maxWidth = windowWidth - SCROLL_BAR_SIZE - TEXT_INSET * 2
-- look for trailing space (work backwards)
-- remember where space is, failing that, split at first character inside width
while #text > 0 do
local width = WindowTextWidth (win, FONT_ID, text) -- how long the text is
-- if it fits, copy whole thing in (splitting at newlines)
if width <= maxWidth then
local t = utils.split (text, "\n")
for _, line in ipairs (t) do
table.insert (lines, line) -- insert into existing text
end -- for
break
end -- the whole lot fits
local col = #text
local split_col = nil
-- keep going until out of columns
while col > 1 do
width = WindowTextWidth (win, FONT_ID, text:sub (1, col))
if width <= maxWidth then
if not split_col then
split_col = col -- in case no space found, this is where we can split
end -- if first time we are smaller than the desired width
-- see if space here
if text:sub (col, col) == " " then
split_col = col
break
end -- if space
end -- if will now fit
col = col - 1
end -- while
-- now find a newline and see if it comes before the space
local newline = string.find (text, "\n")
if newline and newline < split_col then
split_col = newline
end -- if newline found before space
table.insert (lines, text:sub (1, split_col - 1)) -- exclude the newline or space
text = text:sub (split_col + 1) -- bypass the space or newline
end -- while we still have text
-- show result
ShowLines ()
end -- of AddLine
function RemoveLines (count)
assert (type (count) == "number", "In RemoveLines, count is not a number")
if count > #lines then
lines = { }
else
-- remove them individually from the start
for i = 1, count do
table.remove (lines, 1)
end -- for
end -- if
-- display new line
ShowLines ()
end -- of SetText
function GetLineCount ()
return #lines
end -- GetLineCount
function SetTitle (newTitle)
assert (type (newTitle) == "string", "In SetTitle, title is not a string")
title = newTitle
-- display new title
ShowLines ()
end -- of SetTitle
function SetTextColour (foreground, background)
assert (type (foreground) == "number", "In SetTextColour, foreground is not numeric")
assert (type (background) == "number", "In SetTextColour, background is not numeric")
windowTextColour = foreground
windowBackgroundColour = background
ShowLines () -- redisplay
end -- SetTextColour
-- for USA spellings
function SetTextColor (foreground, background)
SetTextColour (foreground, background)
end -- SetTextColor
function SetTitleColour (foreground, background)
assert (type (foreground) == "number", "In SetTitleColour, foreground is not numeric")
assert (type (background) == "number", "In SetTitleColour, background is not numeric")
windowTitleTextColour = foreground
windowTitleBackgroundColour = background
ShowLines () -- redisplay
end -- SetTitleColour
-- for USA spellings
function SetTitleColor (foreground, background)
SetTitleColour (foreground, background)
end -- SetTitleColor
-- show the window
function Show ()
WindowShow (win, true) -- show it
end -- Show
-- hide the window
function Hide ()
WindowShow (win, false) -- hide it
end -- Hide
-- set the scroll position
function SetScrollPosition (pos)
assert (type (pos) == "number", "In SetScrollPosition, position is not numeric")
scrollPos = pos
ShowLines () -- redisplay
end -- SetScrollPosition
-- get the scroll position
function GetScrollPosition ()
return scrollPos
end -- GetScrollPosition
-- set the font
function SetFont (size, name)
assert (type (size) == "number", "In SetFont, size is not numeric")
assert (type (name) == "string", "In SetFont, name is not a string")
fontSize = size
fontName = name
OnPluginInstall () -- set everything up again
end -- SetFont
-- set the Unicode flag
function Unicode (flag)
assert (type (flag) == "boolean", "In Unicode, flag is not boolean")
Utf8 = flag
ShowLines () -- redisplay
end -- Unicode
]]>
</script>
</muclient>