Posted by
| Nick Gammon
Australia (23,158 posts) Bio
Forum Administrator |
Message
| TLDR:
Download the plugin from here (right-click, then save into your MUSHclient / worlds / plugins directory).
Then load that plugin (Shift+Ctrl+P).
Note that you won't see anything until you send the plugin some data, eg.
require "serialize" -- needed to serialize table to string
-- plugin ID needed to call the plugin
ScrollingPlugin = "a160a0dc029b28fc970a935d"
-- set the window title (if an empty string, no title is shown)
CallPlugin (ScrollingPlugin, "SetTitle", "My window title")
-- some example lines
lines = { }
for i = 1, 300 do
lines [i] = string.format ("Line %03i ", i)
end -- for
-- sets the window text (a table of lines)
CallPlugin (ScrollingPlugin, "SetText", serialize.save_simple (lines))
Example of window

Introduction
After a question in another thread, I decided to write an example "scrolling text window" plugin. The intention is to keep stuff (like a chat log) where the text you want to keep might be longer than can conveniently fit into a miniwindow. The window here adds scroll bars (if required) so you can scroll by dragging the thumb around, or by using the mouse wheel.
Simple case
The simple case in a window like this is if everything fits anyway. For example:

Everything fits so we just start drawing the text at the top until we run out of it.
Hard case
If everything doesn't fit then we have a "window" into the text like this:

The scroll thumb shows that we are partway through the actual text. To achieve this we start drawing the text above the window (ie. at a negative position). That way the part we want to see appears in the right place, and the rest is clipped by the miniwindow output routine.
(Note that the title is drawn later so it will appear on top of the line which currently is drawn through the title box).
We now have to draw the scroll bar (a gray box) and a thumb in the middle of it, correctly positioned to where we last left it.
Next a hotspot is added so we know when the scroll thumb is clicked on.
In my display routine I actually move a hotspot which is created once, in order to achieve repositioning the hotspot.
We also need a window drag handler to handle the thumb being dragged around with the mouse down.
When the thumb is moved we can calculate how far we are through the visible window. If you call "a" the length above the thumb, and "b" the length below the thumb, then our position through the visible window will be:
So for example, if we have 10 pixels above the thumb and 20 pixels below the thumb then we are 10/30 = 1/3 of the way through the output lines.
Then we convert that into the number of pixels we need to draw above the start of the window in order to see the correct portion. This is done in the code here:
-- 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
The variable amountThrough is the fraction of the way we are through the possible scroll position.
This is then multiplied by the wanted size (number of lines times the font height) to get a starting position. We subtract out windowClientHeight so that when the scroll thumb is at the bottom the last line of text is at the bottom of the window (not the top).
Mouse wheel scrolling
There is another hotspot which detects the mouse wheel being moved, so that you can scroll with the wheel. This moves the thumb up or down one pixel.
Window movement
To make it easy to reposition the window I use the "movewindow" module described here: http://www.gammon.com.au/forum/?id=9594
The title bar is used as a window drag area. If you don't have a title then the first line of the window serves the same purpose.
Copy to clipboard
In case the user wants to copy the text to the clipboard (eg. if it is a chat window) there is a mouse-up handler that offers a copy menu item. Also on offer is a font selector so the user of the window can choose a font, size and text colour.
How to use in your code
Once installed, you communicate with the plugin by using CallPlugin. This lets you call functions with the plugin, passing arguments to them.
If the title is blank, and there are no lines of text, then the window is hidden (this is the default state when the plugin is loaded).
You can call the following functions. All require the Plugin ID (ScrollingPlugin variable) to identify which plugin to call.
Initial code
require "serialize" -- needed to serialize table to string
-- plugin ID needed to call this plugin
ScrollingPlugin = "a160a0dc029b28fc970a935d"
Send the text to be shown
The text is sent as a serialized table, as shown here:
-- 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 another line
This adds one more line to the table of lines. Useful for just tacking an extra line onto a chat log or similar.
-- add a new line to the end of the table of lines
CallPlugin (ScrollingPlugin, "AddLine", "New line", wrap)
If wrap is true then the text is split into multiple lines (wrapped) if necessary. That way you can send long lines and have them wrapped at the closest space to the right. Note that if you later do a "copy" you will get back the wrapped lines, not the original ones.
Note that if the supplied text contains newline characters ("\n") then the text is wrapped at those characters (this is whether or not the wrap parameter is true). Thus a single call to AddLine might add multiple lines.
Remove lines
Removes one or more lines from the table of lines. Useful for constraining the table of lines to some limit (eg. 500 lines).
-- remove "count" lines from the start of the table of lines
CallPlugin (ScrollingPlugin, "RemoveLines", count)
Find number of lines
Finds how many lines are in the table of lines. Useful to see if the table is getting too large.
-- find number of lines in the lines table
rc, count = CallPlugin (ScrollingPlugin, "GetLineCount")
Set the title
The default title is no title. This gives you slightly more than one extra line for your text.
-- set the window title (if an empty string, no title is shown)
CallPlugin (ScrollingPlugin, "SetTitle", "Example title")
Change the window size
-- example sizes (pixels)
width = 500
height = 300
-- changes scroll window width and height
CallPlugin (ScrollingPlugin, "SetSize" , width, height)
Change the text colour
-- sets the text colour (RGB values)
CallPlugin (ScrollingPlugin, "SetTextColour", foreground, background)
Use ColourNameToRGB to turn a colour name into a numeric colour, for example:
CallPlugin (ScrollingPlugin, "SetTextColour", ColourNameToRGB ("peru"), ColourNameToRGB ("lightgray"))
Change the title bar colour
-- sets the title bar colour (RGB values)
CallPlugin (ScrollingPlugin, "SetTitleColour", foreground, background)
Show the window
-- show the window
CallPlugin (ScrollingPlugin, "Show")
Hide the window
-- hide the window
CallPlugin (ScrollingPlugin, "Hide")
Get and set the scroll position
-- get the scroll position
rc, pos = CallPlugin (ScrollingPlugin, "GetScrollPosition")
-- set the scroll position
CallPlugin (ScrollingPlugin, "SetScrollPosition", position)
Set the font
-- sets the window font
CallPlugin (ScrollingPlugin, "SetFont", size, name)
-- For example:
CallPlugin (ScrollingPlugin, "SetFont", 15, "Courier")
Be cautious that you don't override the font chosen by the user. There is a font choice if you RH-click on the window. If you are planning to use that, don't use this function to change it back.
Set Unicode
CallPlugin (ScrollingPlugin, "Unicode", true)
If called, with the "true" argument, outputting expects UTF-8 text. That lets you show Unicode characters. For this to work you need to be using a Unicode font.
Wrapping
You can use the "wrap" feature of AddLine to have the plugin break long lines at a suitable space. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|