Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ Plugins ➜ Scrolling text window plugin

Scrolling text window plugin

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Nick Gammon   Australia  (23,158 posts)  Bio   Forum Administrator
Date Tue 31 Jan 2017 04:48 AM (UTC)

Amended on Wed 01 Feb 2017 04:39 AM (UTC) by Nick Gammon

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:


position = a / (a + b)


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

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


8,793 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.