1
- --[[ --
2
- InfoBox.lua version 1.1
1
+ --[= [ --
2
+ InfoBox.lua version 1.2
3
3
Encapsulates and enhances Infobar functionality into miniwindows; gauges and status text.
4
- 01 -DEc-08
4
+ 14 -DEc-08
5
5
6
6
by: WillFa (Spellbound on 3k.org:3000)
7
7
portions borrowed or adapted from samples by Nick Gammon.
8
8
9
9
License: Free for public use in your MushClient plugins and scripts as long as credit for this module is
10
10
attributed to WillFa, and Nick Gammon.
11
11
12
+ Assumes that the Sylfaen font is installed on the system. Change line 67 if it is not.
13
+
12
14
Requires: MushClient v. 4.37+ for complete functionality. (CloseWindow() uses DeleteWindow MC function.)
13
15
MushClient v. 4.35+ for basic functionality. (WindowGradient calls)
14
16
@@ -28,11 +30,11 @@ Usage:
28
30
29
31
General Usage is more easily deduced by tprint(InfoBox), tprint(MW), tprint(MW.Bar) rather than reading this source.
30
32
The metatables are setup in such a way that tprint will not recurse up the inheritance chain and spam you.
31
- --]] --
33
+ --]= ] --
32
34
33
35
local world , colour_names = world , colour_names , _M
34
36
local os = {time = os.time }
35
- local math , string , table , bit , utils = math , string , table , bit , utils
37
+ local math , string , table , bit = math , string , table , bit
36
38
local tonumber , tostring , rawget , rawset , type , print = tonumber , tostring , rawget , rawset , type , print
37
39
local unpack , assert , require , getmetatable , setmetatable = unpack , assert , require , getmetatable , setmetatable
38
40
local pairs , ipairs , check = pairs , ipairs , check
@@ -62,19 +64,7 @@ windowPosition = 7
62
64
windowFlags = 0
63
65
64
66
fontID = " fn"
65
-
66
- local fonts = utils .getfontfamilies ()
67
-
68
- if fonts .Sylfaen then
69
- fontName = " Sylfaen"
70
- elseif fonts .Dina then
71
- fontName = " Dina"
72
- elseif fonts [" Lucida Sans Unicode" ] then
73
- fontName = " Lucida Sans Unicode"
74
- else
75
- fontName = " Courier"
76
- end -- if
77
-
67
+ fontName = " Sylfaen"
78
68
fontSize = 10
79
69
fontPadding = 2
80
70
fontBold = true
@@ -245,6 +235,8 @@ end end
245
235
--[=[ Internal Function that draws the pretty boxes ]=] --
246
236
function Draw (self , vOffset , hOffset )
247
237
-- TraceOut (string.format("%s: Window %s Bar %i", "Draw", self.windowName, self.id))
238
+ self .cellTop , self .cellLeft = vOffset , hOffset
239
+ WindowRectOp (self .windowName , 2 , self .cellLeft , self .cellTop - 1 , self .cellLeft + self .cellWidth , self .cellTop + self .cellHeight + self .padding - 2 , self .backgroundColour , nil )
248
240
local Percent = self .value or 0
249
241
local colour , fcolour
250
242
if Percent < self .threshold then
@@ -264,11 +256,11 @@ function Draw (self, vOffset, hOffset)
264
256
local pixels = self .gaugeWidth * Percent / 100
265
257
if self .barStyle > 0 then
266
258
local bezel = {[true ] = 10 , [false ] = 5 }
267
- local frameLeft = hOffset + self .gaugeLeft
268
- local frameTop = vOffset + self .cellHeight - self .gaugeHeight
269
- local frameRight = hOffset + self .gaugeLeft + self .gaugeWidth
270
- local frameBottom = vOffset + self .cellHeight
271
- local topX , topY , bottomX , bottomY = frameLeft + 2 , frameTop + 2 , hOffset + self .gaugeLeft + pixels , frameBottom - 2
259
+ local frameLeft = self . cellLeft + self .gaugeLeft
260
+ local frameTop = self . cellTop + self .cellHeight - self .gaugeHeight
261
+ local frameRight = self . cellLeft + self .gaugeLeft + self .gaugeWidth
262
+ local frameBottom = self . cellTop + self .cellHeight
263
+ local topX , topY , bottomX , bottomY = frameLeft + 2 , frameTop + 2 , self . cellLeft + self .gaugeLeft + pixels , frameBottom - 2
272
264
local colorL , colorR = self .badColour , (fcolour or self .goodColour )
273
265
local ftopX , ftopY , fbottomX , fbottomY = bottomX + 1 , frameTop , frameRight , frameBottom -- fill region for fixed gradients
274
266
if self .anchorRight == true then
@@ -280,9 +272,9 @@ function Draw (self, vOffset, hOffset)
280
272
end
281
273
if bit .band (barStyles .raisedCap , self .barStyle ) == barStyles .raisedCap then
282
274
if self .captionPlacement == 0 then
283
- frameLeft = hOffset + 3
275
+ frameLeft = self . cellLeft + 3
284
276
elseif self .captionPlacement == 3 then
285
- frameRight = hOffset + self .cellWidth - 3
277
+ frameRight = self . cellLeft + self .cellWidth - 3
286
278
end end
287
279
if Percent >= 1 then
288
280
if CheckStyle (self , self .barStyles .solid ) then
@@ -297,12 +289,12 @@ function Draw (self, vOffset, hOffset)
297
289
check (WindowRectOp (self .parent .windowName , 2 , topX , topY , bottomX , bottomY , padFillColour ) )
298
290
if ( (self .anchorRight == false ) and (self .threshold <= 50 ) ) or
299
291
( (self .anchorRight == true ) and (self .threshold > 50 ) ) then -- need more colorR than colorL
300
- check (WindowGradient (self .parent .windowName , hOffset + self .gaugeLeft , frameTop , frameRight - padWidth , bottomY , colorL , colorR , 1 ) )
292
+ check (WindowGradient (self .parent .windowName , self . cellLeft + self .gaugeLeft , frameTop , frameRight - padWidth , bottomY , colorL , colorR , 1 ) )
301
293
elseif ( (self .anchorRight == true ) and (self .threshold <= 50 ) ) or
302
294
( (self .anchorRight == false ) and (self .threshold > 50 ) ) then -- need more colorL than colorR
303
- check (WindowGradient (self .parent .windowName , hOffset + self .gaugeLeft + padWidth , topY , frameRight - 2 , bottomY , colorL , colorR , 1 ) )
295
+ check (WindowGradient (self .parent .windowName , self . cellLeft + self .gaugeLeft + padWidth , topY , frameRight - 2 , bottomY , colorL , colorR , 1 ) )
304
296
end
305
- check (WindowRectOp (self .parent .windowName , 2 , ftopX , ftopY , fbottomX , fbottomY - 1 , self .parent . backgroundColour ) )
297
+ check (WindowRectOp (self .parent .windowName , 2 , ftopX , ftopY , fbottomX , fbottomY - 1 , self .backgroundColour ) )
306
298
elseif CheckStyle (self , self .barStyles .gradientShift ) then -- Thermometer gradients.
307
299
local midpointX = bottomX
308
300
local pixel = self .gaugeWidth / 100
@@ -314,8 +306,8 @@ function Draw (self, vOffset, hOffset)
314
306
check (WindowRectOp (self .parent .windowName , 2 , topX , topY , bottomX , bottomY , (fcolour or self .goodColour ) ) )
315
307
check (WindowRectOp (self .parent .windowName , 2 , ftopX , ftopY , fbottomX , bottomY , self .badColour ) )
316
308
check (WindowGradient (self .parent .windowName , midpointX - gradientWidth , topY , midpointX + gradientWidth , bottomY , colorR , colorL , 1 ) )
317
- check (WindowRectOp (self .parent .windowName , 2 , hOffset + 1 , vOffset , hOffset + self .gaugeLeft , vOffset + self .cellHeight , self . parent .backgroundColour ) )
318
- check (WindowRectOp (self .parent .windowName , 2 , frameRight , frameTop , - 2 , frameBottom , self .parent . backgroundColour ) )
309
+ check (WindowRectOp (self .parent .windowName , 2 , self . cellLeft + 1 , self . cellTop , self . cellLeft + self .gaugeLeft , self . cellTop + self .cellHeight , self .backgroundColour ) )
310
+ check (WindowRectOp (self .parent .windowName , 2 , frameRight , frameTop , - 2 , frameBottom , self .backgroundColour ) )
319
311
end
320
312
if CheckStyle (self , self .barStyles .glass ) then -- glass frame
321
313
local glassWidth , dtX ,dtY , dbX , dbY = pixels , topX , topY , bottomX , bottomY
@@ -329,22 +321,27 @@ function Draw (self, vOffset, hOffset)
329
321
check (WindowImageFromWindow ( self .parent .windowName , self .parent .windowName .. " glass" , self .parent .windowName .. " glass" ) )
330
322
check (WindowBlendImage ( self .parent .windowName , self .parent .windowName .. " glass" , dtX , dtY , dbX , dbY , 21 , .45 ) )
331
323
elseif CheckStyle (self , barStyles .raised + barStyles .raisedCap + barStyles .sunken ) then -- 3D frame rectangle
332
- check (WindowRectOp (self .parent .windowName , 5 , topX , topY , bottomX , bottomY , bezel [not CheckStyle (self , barStyles .sunken + barStyles .glass )] ,1 + 2 + 4 + 8 + 0x1000 ) )
324
+ check (WindowRectOp (self .parent .windowName , 5 , topX , topY , bottomX , bottomY , bezel [not CheckStyle (self , barStyles .sunken + barStyles .glass )] ,0x100F ) )
333
325
end end
334
326
if bit .band ( self .barStyle , 31 ) ~= 0 then -- frame rectangle on border
335
327
local pen = {[true ]= 1 ,[false ]= 5 }
336
328
check (WindowRectOp (self .parent .windowName , pen [CheckStyle (self , self .barStyles .flat )], frameLeft , frameTop , frameRight , frameBottom , bezel [not CheckStyle (self , barStyles .raised + barStyles .raisedCap )], 15 + 0x1000 ) )
337
329
end end
338
- vOffset = vOffset
339
- PrintText (self , vOffset , hOffset )
340
- return vOffset + self .cellHeight + self .padding
330
+ PrintText (self , self .cellTop , self .cellLeft )
331
+ if type (self .button ) == ' table' then
332
+ WindowAddHotspot (self .windowName , self .id , self .cellLeft , self .cellTop , self .cellLeft + self .cellWidth , self .cellTop + self .cellHeight ,
333
+ self .button .mouseOver or " " , self .button .cancelMouseOver or " " , self .button .mouseDown or " " , self .button .cancelMouseDown or " " ,
334
+ self .button .mouseUp or " " , self .button .tooltipText or " " , self .button .cursor or 0 , 0 )
335
+
336
+ end
337
+ return self .cellTop + self .cellHeight + self .padding
341
338
end
342
339
343
340
--[=[ Internal Function that calculates different shades of colors ]=] --
344
341
function DoFade (self )
345
342
-- TraceOut (string.format("%s: Window %s Bar %i", "DoFade", self.windowName, self.id))
346
343
local color
347
- if not self .shades then
344
+ if self . shades == nil or ( self .Bar . shades and self . goodColour ~= self . Bar . goodColour and self . badColour ~= self . Bar . badColour ) then
348
345
self .shades = CalcShades (self , math.ceil (100 - self .threshold )/ 5 )
349
346
end
350
347
if self .value >= self .threshold then
@@ -355,6 +352,18 @@ function DoFade(self)
355
352
return color
356
353
end
357
354
355
+
356
+ --[=[ See :Doc( "Fade" ) --]=] --
357
+ function Bar :Fade (bool )
358
+ assert (bool and type (bool )== " boolean" , " Boolean expected. Got " .. tostring ( bool ) .. " (" .. type (bool ) .. " )" )
359
+ self .fade = bool
360
+ self .shades = nil
361
+ if bool then
362
+ DoFade (self )
363
+ end
364
+ end
365
+
366
+
358
367
--[=[ See :Doc( "TextColour" ) --]=] --
359
368
function Bar :TextColour (x )
360
369
-- TraceOut (string.format("%s: Window %s Bar %i", "TextColour", self.windowName, self.id))
@@ -539,6 +548,19 @@ function _M:New (winName)
539
548
return q
540
549
end
541
550
551
+ --[=[ See :Doc( "BackgroundColour" ) --]=] --
552
+ function _M :BackgroundColour (col )
553
+ assert (col , " Nil passed. specify a colour." )
554
+ local n = tonumber (col ) or ColourNameToRGB (col )
555
+ assert (n and n ~= - 1 ,' Bad value passed. Acceptable examples: "red", 255, 0x0000ff, "#FF0000" - Got ' .. tostring (x ) .. ' (' .. type (x ) .. ' )' )
556
+ self .backgroundColour = n
557
+ self .matteHilight , self .matteShadow = self .backgroundColour ,self .backgroundColour
558
+ for i = 1 ,10 do
559
+ self .matteHilight = AdjustColour (self .matteHilight ,2 )
560
+ self .matteShadow = AdjustColour (self .matteShadow ,3 )
561
+ end
562
+ end
563
+
542
564
--[=[ See :Doc( "Rows" ) --]=] --
543
565
function _M :Rows (num )
544
566
assert (type (num )== " number" and num > 0 , " How many rows? Need a positive number. Got " .. type (num ) )
@@ -606,20 +628,20 @@ function _M:RemoveBar(index)
606
628
end end
607
629
608
630
--[=[ See :Doc( "Update" ) --]=] --
609
- function _M :Update ()
631
+ function _M :Update (force )
610
632
-- TraceOut (string.format("%s: Window %s", "Update", self.windowName))
611
633
assert (self ~= _M , " Pass a table called from " .. _NAME .. " :New(), not " .. _NAME .. " itself." )
612
634
-- Note: It is possible to pass any table instance into this. i.e. foo, foo.Bar, foo.Bars[i]
613
635
-- It may be bad style, but it intentionally will work. foo.Bars[i] still updates the entire window, not just its region.
614
- if os.time () > (self .lastUpdated or 0 ) then
636
+ if os.time () > (self .lastUpdated or 0 ) or force then
615
637
local MiniWindow = self .parent or self
616
638
check (WindowCreate (self .windowName , 0 , 0 , self .windowWidth , self .windowHeight , self .windowPosition , self .windowFlags , GetInfo (278 )) )
617
639
check (WindowRectOp (self .windowName , 2 , 2 , 2 , - 2 , - 2 , self .backgroundColour ) ) -- "erase" miniwindw
618
- local vertical ,horizontal , curRow , curCol , t = 4 , 0 , 1 , 1
640
+ local vertical ,horizontal , curRow , curCol , t = 6 , 0 , 1 , 1
619
641
for _ , curBar in ipairs (self .Bars ) do
620
642
local finishY = vertical + curBar .cellHeight + curBar .padding
621
643
if curRow > self .rows or finishY > self .windowHeight then
622
- vertical = 4
644
+ vertical = 6
623
645
curCol = curCol + 1
624
646
curRow = 1
625
647
if curCol > self .columns then -- Maybe Fonts are distorting the grid
@@ -632,6 +654,7 @@ function _M:Update ()
632
654
curRow = curRow + 1
633
655
end
634
656
check (WindowRectOp (self .windowName , 5 , 0 , 1 , - 1 , - 2 , 10 , 15 ) ) -- 3D border effect on canvas
657
+ WindowRectOp (self .windowName , 2 , self .windowWidth - 2 , 0 , 0 , 0 , GetInfo (278 ), nil )
635
658
WindowShow (self .windowName , true )
636
659
self .lastUpdated = os.time ()
637
660
return true
@@ -675,7 +698,7 @@ function _M:ResizeOutput()
675
698
if self .displaceOutput then
676
699
if self .windowPosition == 9 or self .windowPosition == 10 then
677
700
if sum (9 ,10 ) == 1 then
678
- height = - self .windowHeight
701
+ height = - self .windowHeight - 8
679
702
else
680
703
height = - math.max (math.abs (height ), self .windowHeight )
681
704
end
@@ -833,7 +856,6 @@ function _M:Font(...)
833
856
self .fontName , self .fontSize = name , fontParams [1 ]
834
857
if self == MiniWindow then
835
858
MiniWindow .windowHeight = _M .windowHeight
836
- tp = require " tprint" tp (fontParams )
837
859
check (WindowFont (MiniWindow .windowName , unpack (fontParams ) ) )
838
860
MiniWindow .Bar .cellHeight = WindowFontInfo (MiniWindow .windowName , MiniWindow .fontID , 1 ) + MiniWindow .Bar .cellPadding
839
861
else
@@ -963,7 +985,7 @@ function CalcShades(self, shades) -- the number of shades including start and en
963
985
step .g = (g1 - g2 )/ shades
964
986
step .b = (b1 - b2 )/ shades
965
987
for i = 0 , shades do
966
- Cs [i + 1 ] = tonumber (string.format (" %02x%02x%02x" , math.floor (b1 - (step .b * i )% 256 ) , math.floor (g1 - (step .g * i )% 256 ) , math.floor (r1 - (step .r * i ) )% 256 ),16 )
988
+ Cs [i + 1 ] = tonumber (string.format (" %02x%02x%02x" , math.floor (b1 - (step .b * i ) ) % 256 , math.floor (g1 - (step .g * i ) ) % 256 , math.floor (r1 - (step .r * i ) ) % 256 ),16 )
967
989
end
968
990
Cs [# Cs ] = self .badColour
969
991
return Cs , step , step .r , step .g , step .b
@@ -1549,6 +1571,90 @@ Assuming:
1549
1571
MW,
1550
1572
then InfoBox
1551
1573
]] ,
1574
+
1575
+ [" button" ] = [[
1576
+ Applies To: Bar
1577
+ Protoype: bar.button = {mouseUp = "funcname", ...}
1578
+
1579
+
1580
+ This value expects a table with certain keys paired to the _names_ of functions you write. If there is a table present a Hotspot is added that is drawn over the entire region of the cell (not just the gauge).
1581
+ Missing keys are fine. (i.e. {mouseUp="f"} is OK. {mouseUp="f", mouseDown="", cancelMouseDown=""... is not necessary.)
1582
+
1583
+ Expected keys are named:
1584
+ mouseUp
1585
+ mouseDown
1586
+ cancelMouseDown
1587
+ tooltipText
1588
+ mouseOver
1589
+ cancelMouseOver
1590
+ cursor
1591
+
1592
+ Your functions should be structured as:
1593
+ function myClickFunction (flags, strBarsIndex)
1594
+ local id = tonumber(strBarsIndex) -- because tbl["1"] is a different key than tbl[1]
1595
+ ...
1596
+ MW.Bars[id].caption = "Clicked"
1597
+ end
1598
+ ]] ,
1599
+
1600
+ [" cellTop" ] = [[
1601
+ Applies To: Bar
1602
+ Protoype: x = bar.cellTop
1603
+
1604
+ This value is set by the Update function. It is provided if you wish to add any custom coding and need to know where a bar was drawn. Setting this value produces no effect and will be overwritten the next time the Update function is called.
1605
+ ]] ,
1606
+
1607
+ [" cellLeft" ] = [[
1608
+ Applies To: Bar
1609
+ Protoype: x = bar.cellLeft
1610
+
1611
+ This value is set by the Update function. It is provided if you wish to add any custom coding and need to know where a bar was drawn. Setting this value produces no effect and will be overwritten the next time the Update function is called.
1612
+ ]] ,
1613
+
1614
+ [" Fade" ] = [[
1615
+ Applies To: Bar
1616
+ Protoype: bar:Fade(bool)
1617
+
1618
+ Calling this function sets the fade value and recalculates the shades table to which the fade effect refers. It's not required to call this function, since the draw routine will recalculate the shades table if necessary. There is an interesting bug that can be exploited by calling this function however.
1619
+
1620
+ Try the following:
1621
+ for x = 100,30,-10 do
1622
+ local foo = MW:AddBar("", x, "green", "red", false, MW.barStyles.glass + MW.barStyles.gradientScale)
1623
+ foo:Fade(true)
1624
+ foo.badColour = colour_names.dodgerblue
1625
+ end
1626
+
1627
+ It's a bug, but it looks cool. Also this is why using the functions to set values is recommended!
1628
+ ]] ,
1629
+
1630
+ [" cellWidth" ] = [[
1631
+ Applies To: Bar
1632
+ Protoype: x = bar.cellWidth
1633
+
1634
+ The value for this property is generated by the Miniwindow's __index metamethod. The function in the metamethod returns (windowWidth / columns) for you. You should never have a reason to set your own value, and doing so will probably break things in uncool ways.
1635
+ ]] , -- ']]
1636
+
1637
+ [" *AddYourOwn" ] = [[
1638
+ Applies To: ALL
1639
+ Protoype: N/A
1640
+
1641
+ A Bar is a table, after all, and you might find it useful to attach your own data, or a reference, to a bar. This is mostly safe to do as the module uses the pairs() and ipairs() functions in limited places.
1642
+ pairs() is used to copy InfoBox.Bar to MW.Bar
1643
+ ipairs() is used on the MW.Bar table to find the functions for the default parameters for AddBar.
1644
+ ipairs() is used on the MW.Bars table to draw the bars.
1645
+
1646
+ Other than avoiding numerical indices in the 2 Bar(s) tables, it should be safe to add to a table as you see fit.
1647
+ ]] ,
1648
+
1649
+ --[=[
1650
+ [""] =[[
1651
+ Applies To:
1652
+ Protoype:
1653
+
1654
+
1655
+ ]],
1656
+
1657
+ --]=] -- ']]
1552
1658
}
1553
1659
1554
1660
function Doc (self , topic )
0 commit comments