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.
 Entire forum ➜ MUSHclient ➜ Miniwindows ➜ How to implement a miniwindow with tab options

How to implement a miniwindow with tab options

Posting of new messages is disabled at present.

Refresh page


Posted by Zhenzh   China  (68 posts)  Bio
Date Tue 06 Feb 2018 01:44 AM (UTC)
Message
I'm going to capture a batch of information into miniwidow such as hp,mana,skills,chats and etc.

The problem is that there is too much information to be shown in the one miniwindow.

I'd like to generate an miniwindow which includes several tab options to resolve the problem so that I can separate information into different tab page. For example, when clicking status tab, hp and mana related information will be shown. When clicking skills tab, all my owned skills will be listed in miniwindow.

Is there any existing plugin which can implement the tab options?
Top

Posted by Fiendish   USA  (2,533 posts)  Bio   Global Moderator
Date Reply #1 on Tue 06 Feb 2018 03:28 AM (UTC)
Message
Quote:
Is there any existing plugin which can implement the tab options?


Not here.

https://github.com/fiendish/aardwolfclientpackage
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #2 on Tue 06 Feb 2018 06:22 AM (UTC)

Amended on Tue 06 Feb 2018 06:25 AM (UTC) by Nick Gammon

Message
It's a good question, and something I've been planning to demonstrate for a while. Tabbed windows have three major things:


  • A title bar showing the name of the currently-active tab, and which lets you drag the window around
  • The "client" area which changes depending on the selected tab
  • The tabs at the bottom (or top, or wherever) which let you change tabs, and also show (by the way they are drawn) what the current tab is


The plugin below implements a demonstration of that, hopefully in a modular-enough format for you to adapt to your needs.

Template:saveplugin=TabDemo To save and install the TabDemo plugin do this:
  1. Copy between the lines below (to the Clipboard)
  2. Open a text editor (such as Notepad) and paste the plugin into it
  3. Save to disk on your PC, preferably in your plugins directory, as TabDemo.xml
  4. Go to the MUSHclient File menu -> Plugins
  5. Click "Add"
  6. Choose the file TabDemo.xml (which you just saved in step 3) as a plugin
  7. Click "Close"



<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>

<muclient>
<plugin
   name="TabDemo"
   author="Nick Gammon"
   id="302097c20a726d174b9d692a"
   language="Lua"
   purpose="Demonstrates a tabbed miniwindow"
   date_written="2018-02-06 15:24:08"
   requires="5.00"
   save_state="y"
   version="1.0"
   >
<description trim="y">
<![CDATA[
Demonstrates doing a miniwindow with tabs.
]]>
</description>

</plugin>

<!--  Script  -->

<script>
<![CDATA[

-- colours
background_colour = ColourNameToRGB "lightskyblue"
frame_colour      = ColourNameToRGB "mediumorchid"
title_bar_colour  = ColourNameToRGB "palegoldenrod"
title_colour      = ColourNameToRGB "mediumblue"
tab_colour        = ColourNameToRGB "green"
tab_text_colour   = ColourNameToRGB "white"

-- miniwindow size
window_width = 300
window_height = 200

-- gap between text in tabs
tab_filler = 10

-- -------------------------------------------------------------------------------
-- Handlers for drawing the contents of each tab
-- -------------------------------------------------------------------------------

function DrawCircle (left, top, right, bottom)
  local circle_size = 60
  
  WindowRectOp (win,  miniwin.rect_fill, -- fill
                left, top, right, bottom,
                ColourNameToRGB "peachpuff")
                
  WindowCircleOp (win, miniwin.circle_ellipse, -- circle
                  (right - left) / 2 - circle_size / 2, (bottom - top) / 2 - circle_size / 2,   -- Left, Top,
                  (right - left) / 2 + circle_size / 2, (bottom - top) / 2 + circle_size / 2,   -- Right, Bottom
                  ColourNameToRGB("blue"), miniwin.pen_solid, 2, -- pen width 2
                  ColourNameToRGB("cyan"), miniwin.brush_solid)  -- brush
end -- DrawCircle


function DrawSquare (left, top, right, bottom)
  local square_size = 80
  
  WindowRectOp (win,  miniwin.rect_fill, -- square
                  (right - left) / 2 - square_size / 2, (bottom - top) / 2 - square_size / 2,   -- Left, Top,
                  (right - left) / 2 + square_size / 2, (bottom - top) / 2 + square_size / 2,   -- Right, Bottom
                  ColourNameToRGB("lightcoral"), miniwin.pen_solid, 2, -- pen width 2
                  ColourNameToRGB("violet"), miniwin.brush_solid)  -- brush
end -- DrawSquare

function DrawArrow (left, top, right, bottom)
  WindowPolygon (win, "20,50,180,50,180,20,230,70,180,120,180,90,20,90",
                          ColourNameToRGB("cyan"),   miniwin.pen_solid, 3,   -- pen (solid, width 3)
                          ColourNameToRGB("yellow"), miniwin.brush_solid,    -- brush (solid)
                          true,    -- fill
                          false)   -- alternate fill
end -- DrawArrow

function DrawPie (left, top, right, bottom)
  local pie_size = 80
  
  WindowCircleOp (win, miniwin.circle_pie,    -- pie
          (right - left) / 2 - pie_size / 2, (bottom - top) / 2 - pie_size / 2,   -- Left, Top,
          (right - left) / 2 + pie_size / 2, (bottom - top) / 2 + pie_size / 2,   -- Right, Bottom
          ColourNameToRGB("green"), miniwin.pen_solid, 2,  -- pen width 2
          ColourNameToRGB("cyan"), miniwin.brush_solid,    -- brush
          0, right,     -- the x, y position of the pie's starting point
          right, bottom)     -- the x, y position of the pie's ending point
end -- DrawPie
    
-- -------------------------------------------------------------------------------
-- tabs - table of all available tabs
-- -------------------------------------------------------------------------------    
tabs = {
    { name = "Circle", handler = DrawCircle },
    { name = "Square", handler = DrawSquare },
    { name = "Arrow",  handler = DrawArrow },
    { name = "Pie",    handler = DrawPie },
    } -- end of tabs
    
active_tab = 1
    
-- -------------------------------------------------------------------------------
-- OnPluginInstall
-- -------------------------------------------------------------------------------
function OnPluginInstall ()
  
  win = GetPluginID ()
  font_id = "fn"
  
  font_name = "Lucida Console"    -- the font name
  
  require "movewindow"  -- load the movewindow.lua module

  -- install the window movement handler, get back the window position
  windowinfo = movewindow.install (win, miniwin.pos_top_left)  -- default to top left
   
  -- make window so I can grab the font info
  WindowCreate (win, 
                 windowinfo.window_left, 
                 windowinfo.window_top, 
                 window_width, window_height,
                 windowinfo.window_mode,   
                 windowinfo.window_flags,
                 background_colour) 

  WindowFont (win, font_id, font_name, 8, false, false, false, false, 0, 0)  -- normal  
  font_height = WindowFontInfo (win, font_id, 1)  -- height
 
  client_bottom = window_height - font_height - 8
   
  DrawWindow (1)  
 
end -- OnPluginInstall

-- -------------------------------------------------------------------------------
-- OnPluginSaveState
-- -------------------------------------------------------------------------------
function OnPluginSaveState ()
  -- save window current location for next time  
  movewindow.save_state (win)
end -- function OnPluginSaveState

-- -------------------------------------------------------------------------------
-- mousedown - handle clicking on a tab
-- -------------------------------------------------------------------------------
function tab_mouse_down (flags, hotspot_id)
  local whichTab = string.match (hotspot_id, "^hs(%d)$")
  if not whichTab then  -- tab unknown for some reason
    return
  end -- if
  
  DrawWindow (tonumber (whichTab))
  
end -- tab_mouse_down

-- -------------------------------------------------------------------------------
-- DrawWindow - draw the tabbed window
-- -------------------------------------------------------------------------------
function DrawWindow (whichTab)

  active_tab = whichTab
  
  -- clear window
  WindowRectOp (win, miniwin.rect_fill, 0, 0, 0, 0, background_colour)
  WindowDeleteAllHotspots (win)

    -- draw drag bar rectangle
  WindowRectOp (win, miniwin.rect_fill, 1, 1, 0, font_height + 2, title_bar_colour)

  -- add the drag handler so they can move the window around
  movewindow.add_drag_handler (win, 0, 0, 0, font_height)

  local thisTab = tabs [whichTab]
  
  -- find title width so we can center it
  title_width = WindowTextWidth (win, font_id, thisTab.name)
  
  -- draw title
  WindowText(win, font_id, thisTab.name, (window_width - title_width )/ 2 + 1, 1, 0, 0, title_colour)

  -- frame window
  WindowRectOp (win, miniwin.rect_frame, 0, 0, 0, 0, frame_colour)
  
  -- draw tabs
  
  local left = 1
  
  for k, v in ipairs (tabs) do
    local tab_width =  WindowTextWidth (win, font_id, v.name)
    
    -- tab background
    WindowRectOp (win, miniwin.rect_fill, left, client_bottom, left + tab_width + tab_filler, window_height - 1, tab_colour)

    -- tab text
    WindowText(win, font_id, v.name, left + tab_filler / 2, client_bottom + 4, 0, 0, tab_text_colour)
    
    -- draw upper line if not active tab
    if k ~= whichTab then
      WindowLine(win, left, client_bottom + 2, left + tab_width + tab_filler, client_bottom + 2, 
                  ColourNameToRGB "lightgray", miniwin.pen_solid, 2)
    end -- if not active
    
    -- draw lower line
    WindowLine(win, left, window_height - 1, left + tab_width + tab_filler, window_height - 1, 
                ColourNameToRGB "lightgray", miniwin.pen_solid, 1)
    
    -- draw vertical lines
    WindowLine(win, left, client_bottom + 2, left, window_height - 1, 
                ColourNameToRGB "lightgray", miniwin.pen_solid, 1)
    WindowLine(win, left + tab_width + tab_filler, client_bottom + 2, left + tab_width + tab_filler, window_height - 1, 
                ColourNameToRGB "lightgray", miniwin.pen_solid, 1)

    -- now add a hotspot for this tab
    WindowAddHotspot(win, "hs" .. k,  
                     left, client_bottom, left + tab_width + tab_filler, window_height - 1,   -- rectangle
                     "",   -- mouseover
                     "",   -- cancelmouseover
                     "tab_mouse_down",
                     "",  -- cancelmousedown
                     "",   -- mouseup
                     "Select " .. v.name .. " tab",  -- tooltip text
                     miniwin.cursor_hand, 0)  -- hand cursor
                         
    left = left + tab_width + tab_filler
    
  end -- for each tab
  
  -- call handler to draw rest of window
  local handler = thisTab.handler
  if handler then
    handler (1, font_height + 2, window_width - 1, client_bottom)
  else
    ColourNote ("orange", "", "No tab handler for " .. thisTab.name)
  end -- if
  
  WindowShow (win, true) 
end -- DrawWindow

]]>
</script>
</muclient>


You shouldn't need to change much of it, except the "tab handlers" which draw the contents of the tabs (only one is drawn at a time, of course) and the table of tabs, which refers to the tab handlers.

Example of it in operation:









The tab handlers are given the dimensions of the "client" area (left, top, right, bottom) which is where they should draw inside. You can use that, for example, to clear the client area as I did in the case of the circle.

You can see that the active tab looks a bit different (at the bottom) and the name of the currently-selected tab appears in the title area.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Zhenzh   China  (68 posts)  Bio
Date Reply #3 on Tue 06 Feb 2018 06:49 AM (UTC)
Message
It's so cool. I'll try to adjust this code to satisfy the MUD I'm playing.

Definitely, I will feedback to you if I have any finding or updates during my using the plugin.
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #4 on Tue 06 Feb 2018 11:37 PM (UTC)

Amended on Sat 19 May 2018 02:51 AM (UTC) by Nick Gammon

Message
For simplicity of use, I've turned it into a Lua module. The source can be obtained here:

https://github.com/nickgammon/mushclient/blob/master/lua/tabbed_window.lua

Raw file: tabbed_window.lua

(RH-click to download it to your PC).

It has been reworked somewhat to allow for multiple tabbed windows. Thus you supply a "context" which is the information for this particular window (eg. window ID, font name, font size, colours etc.). Most of it has default.

A minimal implementation would be:


require "tabbed_window"

function DrawFoo (win, left, top, right, bottom, context)
  WindowText (win, context.tabfont.id, "This is the foo tab", left + 10, top + 10, 0, 0, ColourNameToRGB "green")
end -- DrawStats

function DrawBar (win, left, top, right, bottom, context)
  WindowText (win, context.tabfont.id, "This is the bar tab", left + 10, top + 10, 0, 0, ColourNameToRGB "darkblue")
end -- DrawEquipment

context = { 

 win = "tabbed_window" .. GetPluginID (),

 tabs = {
      { name = "Foo",       handler = DrawFoo },
      { name = "Bar",       handler = DrawBar },
      } -- end of tabs
    }  -- end of context
    
        
tabbed_window.init (context)
tabbed_window.draw_window (context, 1)


This will draw a window with two tabs: Foo and Bar.

You could make a second tabbed window by creating a new context table (eg. context2) and then doing the "init" and "draw_window" as above. Each window would need to have its own window ID (win) in the context so that different windows are created.




The plugin below demonstrates setting up two tabbed windows, with saving the window position, etc.

Template:saveplugin=Tab_module_test To save and install the Tab_module_test plugin do this:
  1. Copy between the lines below (to the Clipboard)
  2. Open a text editor (such as Notepad) and paste the plugin into it
  3. Save to disk on your PC, preferably in your plugins directory, as Tab_module_test.xml
  4. Go to the MUSHclient File menu -> Plugins
  5. Click "Add"
  6. Choose the file Tab_module_test.xml (which you just saved in step 3) as a plugin
  7. Click "Close"




<?xml version="1.0" encoding="iso-8859-1"?>

<muclient>
<plugin
   name="Tab_module_test"
   author="Nick Gammon"
   id="ad093daf13a156bb4ddf6854"
   language="Lua"
   purpose="Tests the tabbed_window module"
   save_state="y"
   date_written="2018-02-07 08:45:31"
   date_modified="2018-02-08 13:15:00"
   requires="5.01"
   version="1.0"
   >
<description trim="y">
<![CDATA[
Demonstration of using tabbed_window.lua
]]>
</description>

</plugin>

<!--  Script  -->

<script>
<![CDATA[

package.path = 'c:/source/mushclient/lua/?.lua'
require "tabbed_window"

-- -------------------------------------------------------------------------------
-- First tabbed window
-- -------------------------------------------------------------------------------

function DrawCircle (win, left, top, right, bottom, context)

  -- fill client area first
  WindowRectOp (win,  miniwin.rect_fill, -- fill
                left, top, right, bottom,
                ColourNameToRGB "peachpuff")

  WindowCircleOp (win, miniwin.circle_ellipse, -- circle
                  60, 60, 120, 120,                -- Left, Top, Right, Bottom
                  ColourNameToRGB("blue"), miniwin.pen_solid, 2, -- pen width 2
                  ColourNameToRGB("cyan"), miniwin.brush_solid)  -- brush
end -- DrawCircle


function DrawSquare (win, left, top, right, bottom, context)
  local square_size = 80

  WindowRectOp (win,  miniwin.rect_fill, -- square
                  (right - left) / 2 - square_size / 2, (bottom - top) / 2 - square_size / 2,   -- Left, Top,
                  (right - left) / 2 + square_size / 2, (bottom - top) / 2 + square_size / 2,   -- Right, Bottom
                  ColourNameToRGB("lightcoral"), miniwin.pen_solid, 2, -- pen width 2
                  ColourNameToRGB("violet"), miniwin.brush_solid)  -- brush
end -- DrawSquare

function DrawArrow (win, left, top, right, bottom, context)
  WindowPolygon (win, "20,50,180,50,180,20,230,70,180,120,180,90,20,90",
                          ColourNameToRGB("cyan"),   miniwin.pen_solid, 3,   -- pen (solid, width 3)
                          ColourNameToRGB("yellow"), miniwin.brush_solid,    -- brush (solid)
                          true,    -- fill
                          false)   -- alternate fill
end -- DrawArrow

function DrawPie (win, left, top, right, bottom, context)
  local pie_size = 80

  WindowCircleOp (win, miniwin.circle_pie,    -- pie
          (right - left) / 2 - pie_size / 2, (bottom - top) / 2 - pie_size / 2,   -- Left, Top,
          (right - left) / 2 + pie_size / 2, (bottom - top) / 2 + pie_size / 2,   -- Right, Bottom
          ColourNameToRGB("green"), miniwin.pen_solid, 2,  -- pen width 2
          ColourNameToRGB("cyan"), miniwin.brush_solid,    -- brush
          0, right,     -- the x, y position of the pie's starting point
          right, bottom)     -- the x, y position of the pie's ending point
end -- DrawPie

context1 = {

 win = "tabbed_window_test1",

 tabs = {
      { name = "Circle", handler = DrawCircle },
      { name = "Square", handler = DrawSquare },
      { name = "Arrow",  handler = DrawArrow },
      { name = "Pie",    handler = DrawPie },
      } -- end of tabs
    } -- end of context1


-- -------------------------------------------------------------------------------
-- Second tabbed window
-- -------------------------------------------------------------------------------

function DrawStats (win, left, top, right, bottom, context)
  WindowText (win, context.tabfont.id, "Here are the stats", left + 10, top + 10, 0, 0, ColourNameToRGB "green")
end -- DrawStats

function DrawEquipment (win, left, top, right, bottom, context)
  WindowText (win, context.tabfont.id, "Here is the equipment", left + 10, top + 10, 0, 0, ColourNameToRGB "darkblue")
end -- DrawEquipment

function DrawHealth (win, left, top, right, bottom, context)
  WindowText (win, context.tabfont.id, "Here is my health", left + 10, top + 10, 0, 0, ColourNameToRGB "red")
end -- DrawHealth

context2 = {

 win = "tabbed_window_test2",
 font = {
    size = 15,
    name = 'Fixedsys'
    },

 window = {
  width = 600,
  height = 300,
  }, -- end of window info

 -- table of tabs with the name and a handler function for each one
 tabs = {
      { name = "Stats",     handler = DrawStats },
      { name = "Equipment", handler = DrawEquipment },
      { name = "Health",    handler = DrawHealth },
      } -- end of tabs

    }  -- end of context2


function OnPluginInstall ()
  tabbed_window.init (context1)
  tabbed_window.init (context2)

  tabbed_window.draw_window (context1, 1)
  tabbed_window.draw_window (context2, 1)
end -- OnPluginInstall

-- -------------------------------------------------------------------------------
-- OnPluginSaveState
-- -------------------------------------------------------------------------------
function OnPluginSaveState ()
  -- save window current location for next time
  tabbed_window.save_state (context1)
  tabbed_window.save_state (context2)
end -- function OnPluginSaveState

-- -------------------------------------------------------------------------------
-- OnPluginClose
-- -------------------------------------------------------------------------------
function OnPluginClose ()
    -- if enabled
    if GetPluginInfo (GetPluginID(), 17) then
        OnPluginDisable()
    end -- if enabled
end -- function OnPluginClose

-- -------------------------------------------------------------------------------
-- OnPluginEnable
-- -------------------------------------------------------------------------------
function OnPluginEnable ()
    WindowShow (context1.win, true)
    WindowShow (context2.win, true)
end -- function OnPluginEnable


-- -------------------------------------------------------------------------------
-- OnPluginDisable
-- -------------------------------------------------------------------------------
function OnPluginDisable ()
    WindowShow (context1.win, false)
    WindowShow (context2.win, false)
end -- function OnPluginDisable

]]>
</script>

</muclient>


[EDIT] Added code to hide the windows if you close or disable the plugin.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Zhenzh   China  (68 posts)  Bio
Date Reply #5 on Wed 07 Feb 2018 01:20 PM (UTC)
Message
I have tried the plugin and it do works perfect.

There are two comments during my adjusting:

#1 In each tab window, I'd like to use different font setting for title,tab and client(bold for active tab text, larger font size for title).
So I think the font context can be more detailed to draw a richer tab window.

#2 Some tab may be used for chats capturing which needs scroll up/down to browser history. It would be better adding a scroll bar switch to manually control in the specified tab window.
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #6 on Thu 08 Feb 2018 02:25 AM (UTC)
Message
Zhenzh said:

#1 In each tab window, I'd like to use different font setting for title,tab and client(bold for active tab text, larger font size for title).
So I think the font context can be more detailed to draw a richer tab window.


I've modified the Lua module to support that. The post above has been amended slightly, and you will need to download the latest version from GitHub.

You now have three fonts:


  • Inactive tab font
  • Active tab font (eg. bold)
  • Title font


In each case you can specify a different point size, and whether they are to be in bold, italic and what font.

You can of course add your own fonts to the miniwindow.

Zhenzh said:

#2 Some tab may be used for chats capturing which needs scroll up/down to browser history. It would be better adding a scroll bar switch to manually control in the specified tab window.


Scrolling is just another special case of what to draw in the client area. You can draw text, shapes, a cat, whatever.

I have an example of doing scrolling text here:

http://www.gammon.com.au/forum/?id=13916

You may need to tweak it a bit to make it draw into the "client" area of the tabbed window rather than the whole area. Still, the scrolling text plugin should give you some helpful idea.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Zhenzh   China  (68 posts)  Bio
Date Reply #7 on Thu 08 Feb 2018 07:15 AM (UTC)
Message
Thank you for your kindly support.

It do helps me a lot.
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.


23,828 views.

Posting of new messages is disabled at present.

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.