murgaLua FLTK Menu System Problems


Forum: Programming and Scripting
Topic: murgaLua FLTK Menu System Problems
started by: mav_it

Posted by mav_it on Oct. 29 2007,17:38
Hi to all,

Sorry for the inconvenience, but I have a problem using callbacks in the murgaLua FLTK Menu bar. I have managed to create the menu bar with sub menus, but I'm not capable of inserting callbacks for menu items to do something useful.
The code is the following (I was trying to converto to murgaLua the FLTK editor example in the FLTK documentation) :



Code Sample

#!/bin/lua

ww = 800
wh = 600

window = fltk:Fl_Double_Window(ww,wh,"My first little app")

textbuf = fltk:Fl_Text_Buffer();

--- Debug only : show something in the editing area
textbuf:loadfile("editor.lua");
--editor = fltk:Fl_Text_Editor(10,30,ww-20,wh-30)
editor = fltk:Fl_Text_Editor(10,30,ww-20,wh-60)
editor:buffer(textbuf)


-- Callbacks for menu items
function open_cb(object)
end

function insert_cb(object)
end

function save_cb(object)
end

function saveas_cb(object)
end

function view_cb(object)
end

function close_cb(object)
end

function quit_cb(object)
   if fltk.fl_choice("Are you sure ?","No",nil,"Yes") >= 1 then
       window:hide()
   end  
end



btn = fltk:Fl_Button((ww / 2)-30,(wh-30),60,30,"QUIT")
btn:callback(quit_cb)

--- Build Up dynamically the menu:
--- Dont know how to pass a table statically
mb = fltk:Fl_Menu_Bar(0,0,800,30)
mb:add("&File/&New File", 0, new_cb)
mb:add("&File/&Insert File", 0, insert_cb)
mb:add("&File/&Save File", 0, save_cb)
mb:add("&File/Save File &As", 0, saveas_cb)
mb:add("&File/New &View", 0, view_cb)
mb:add("&File/&Close View", 0, close_cb)
mb:add("&File/E&xit", 0, quit_cb)

mb:add("&Edit",0, 0, 0, FL_SUBMENU)
mb:add("&Search",0, 0, 0, FL_SUBMENU)
mb:add("&Help",0, 0, 0, FL_SUBMENU)

window:show()
Fl:run()



The only callback that is not empty is the exit callback, that I have also used for the big QUIT button below: used in the QUIT button, the
Code Sample
quit_cb()
callback works very well, what I do wrong when I use it in the add menu function ?

Thank You in advance,

Mauro

Posted by roberts on Oct. 29 2007,18:53
Probably many ways...
But I would add a callback to mb

mb:callback(menuItem)

Then you can choose to use value or text to retrieve menu item selected. Value is a numerical index into the Fl_menu array or text is the actual value of the menu item.

Make a new function like this:

function menuItem(object)
  print(object:value())
end


Run this from console and you will see the index value printing. Then you could use this in a case statement to determine what code or function to call.

Or use

  print(object:text())

if you prefer to use the text values of the menu items.

Posted by mikshaw on Oct. 29 2007,19:06
The menu features are not fully supported at this time, including individual callbacks for individual menu items.

The only thing I've found to work so far is to make a single callback for the whole menu. In that callback function you test the menu text and run the appropriate function as a result.

for example:
Code Sample
mb:callback(
function()
 if mb:text()=="&New File" then open_cb()
 elseif mb:text()=="&Insert File" then insert_cb()
 end
end
)


EDIT:
Quote
choose to use value or text to retrieve menu item selected
I forgot about the nurmerical value.

Posted by mav_it on Oct. 29 2007,20:36
Thank you very much to you both, I will try these methods now.

Mauro.

Posted by mav_it on Nov. 05 2007,22:54
I have managed to reach what I think is a show-stopper.. :(
I have addressed many missing (unimplmented ? ) functions, but currently I cannot impement serching within the text buffer, since using the Fl_text_buffer:search_forward(), or Fl_textBuffer:search backward(), murgaLua gives a "search_forward nil method" error.

Anyway, by using keyboard, the editor is working, except for find/replace functions.

The portion of the code that is not working is :

Code Sample

-- SEARCH MENU CALLBACKS
function find_cb()
   local str
   local fnd
   str = fltk.fl_input("Insert a string to search", lastsearch)
   if (str ~= 0) then
fnd = tb:search_forward(0,str,fnd,0)
if (fnd ~= 0) then
   tb:select(fnd, tb:word_end(fnd))
else
   fltk.fl_message("String " .. str .. "Not found!")
end
   end
end

Here, the tb:search_forward(0,str,fnd,0) (tb is a Text_Buffer variable) does not work, and MurgaLua gives:

Code Sample

attempt to call method "search_forward" : a nil value


I suspect that this method has not been implemented in MurgaLua.


The complete editor, should anyone find it useful for anything, is  the following (note that the replace dialog is not implemented, being not able to perform the search...  :(

Code Sample
#!/bin/lua

version = "0.01"

ww = 1024
wh = 768

title = "MURGA LUA FLTK EDITOR - "

-- -- Main window
w = fltk:Fl_Double_Window(ww,wh,title)
-- -- Text Buffer to hold file to edit
tb = fltk:Fl_Text_Buffer();

changed = false
filename = ""
saved = true
newfile = false
lastsearch = ""

-- This will be used to hold copied / cutted text
clipboard = ""

-- Editor widget will work for standard keyboard shortcuts
ed = fltk:Fl_Text_Editor(10,30,ww-20,wh-60)
ed:buffer(tb)


function ask_save(object)
   if (not saved) then
if fltk.fl_choice("There are unsevd Buffers. Do you want to save ?","No",nil,"Yes") >= 1 then
   save_cb()
end
   end
end

-- check if we need to save to close
function check_save(object)
   if (not saved) then
if fltk.fl_choice("There are unsevd Buffers. Do you Really want to exit ?","No",nil,"Yes") >= 1 then
   w:hide()
end
   else
w:hide()
   end
end

w:callback(check_save)

-- Callback for menu bar
function menuItem(object)
   --print(mb:text() .. ' --> ' .. mb:value())    
   if (mb:text()=="&New File") then new_cb()  

-- FILE MENU
elseif (mb:text()=="&Open File") then open_cb()  
elseif (mb:text()=="&Insert File") then insert_cb()  
elseif (mb:text()=="&Save File") then save_cb()  
elseif (mb:text()=="Save File &As") then saveas_cb()  
elseif (mb:text()=="E&xit") then exit_cb()

-- EDIT MENU
elseif (mb:text()=="&Undo") then undo_cb()
elseif (mb:text()=="Cu&t") then cut_cb()
elseif (mb:text()=="&Copy") then copy_cb()
elseif (mb:text()=="&Paste") then paste_cb()
elseif (mb:text()=="&Delete") then delete_cb()

-- SEARCH MENU
elseif (mb:text()=="&Find...") then find_cb()
elseif (mb:text()=="Find &Again") then findagain_cb()
elseif (mb:text()=="&Replace...") then replace_cb()
elseif (mb:text()=="Re&place Again") then replaceagain_cb()

-- HELP MENU
elseif (mb:value()==24) then about_cb()
   end
end

-- FILE MENU CALLBACKS

function new_cb()
   ask_save()
   newfile = true
   filename = "untitled"
   saved = false
   tb:remove(1,tb:length())
   w:label(title .. filename)
end

function open_cb()
   ask_save()
   filename = fltk.fl_file_chooser("Select File to open", nil, nil, 0)
   if (filename ~= nil) then
tb:loadfile(filename)
w:label(title .. filename)
saved = false
   end
end

function insert_cb()
   local fname = fltk.fl_file_chooser("Select File to insert", nil, nil, 0)
   if (fname ~= nil) then
local pos = ed:insert_position()
tb:insertfile(fname,pos)
   end
end

function save_cb()
   if (untitled) then
saveas_cb()
   elseif (not saved) then
if (tb:savefile(filename)) then
   saved = true
   fltk.fl_message("File " .. filename .. " Saved.")
else
   fltk.fl_alert("Error writing file " .. filename)
end
   end
   
end

function saveas_cb()
   local fname = fltk.fl_file_chooser("FILENAME TO SAVE", nil, nil, 0)
   if (fname ~= nil) then
if (tb:savefile(fname)) then
   filename = fname
   w:label(title .. filename)
   saved = true
   fltk.fl_message("File " .. filename .. " Saved.")
else
   fltk.fl_alert("Error writing file " .. filename)
end
   end
end

function close_cb()
   ask_saved()
end

function exit_cb()
   check_save()
end

-- EDIT MENU CALLBACKS
function undo_cb()
end

function cut_cb()
   if ( tb:selected() ~= 0) then
       clipboard = tb:selection_text()
tb:remove_selection()    
   end
end

function copy_cb()
   if (tb:selected() ~= 0) then
clipboard = tb:selection_text()
   end
end

function paste_cb()
   local pos = ed:insert_position()
   tb:insert(pos,clipboard)
end

function delete_cb()
   if (tb:selected() ~= 0) then
tb:remove_selection()
   end
end

-- SEARCH MENU CALLBACKS
function find_cb()
   local str
   local fnd
   str = fltk.fl_input("Insert a string to search", lastsearch)
   if (str ~= 0) then
fnd = tb:search_forward(0,str,fnd,0)
if (fnd ~= 0) then
   tb:select(fnd, tb:word_end(fnd))
else
   fltk.fl_message("String " .. str .. "Not found!")
end
   end
end

function findagain_cb()
end

function replace_cb()
   replace_dlg:show()
end

function replaceagain_cb()
end


-- HELP CALLBACKS
function about_cb()
   fltk.fl_message("MURGA LUA FLTK EDITOR\n\nMurga Lua Version of an FLTK editor example\nBy mav_it\n\nVersion " .. version)
end

--- Build Up dynamically the menu:
mb = fltk:Fl_Menu_Bar(0,0,ww,30)
mb:callback(menuItem)

mb:add("&File/&New File", 0, 0)
mb:add("&File/&Open File", 0, 0)
mb:add("&File/&Insert File", 0, 0)
mb:add("&File/&Save File", 0, 0)
mb:add("&File/Save File &As", 0, 0)
mb:add("&File/E&xit", 0, 0)  


mb:add("&Edit/&Undo", 0, 0)
mb:add("&Edit/Cu&t", 0, 0)
mb:add("&Edit/&Copy", 0, 0)
mb:add("&Edit/&Paste", 0, 0)
mb:add("&Edit/&Delete", 0, 0)


mb:add("&Search/&Find...", 0, 0)
mb:add("&Search/Find &Again", 0, 0)
mb:add("&Search/&Replace...", 0, 0)
mb:add("&Search/Re&place Again",0, 0)


mb:add("&Help/&About", 0, 0)

--This does not seem to be implemented in MurgaLua FLTK
--tb:add_modify_callback(changed_cb, w)
--tb:call_modify_callbacks()

-- REPLACE DIALOG
replace_dlg = fltk:Fl_Window(300, 105, "Replace")
replace_find = fltk:Fl_Input(70, 10, 200, 25, "Find:")
replace_with = fltk:Fl_Input(70, 40, 200, 25, "Replace:")
replace_all   = fltk:Fl_Button(10, 70, 90, 25, "Replace All")
replace_next   = fltk:Fl_Return_Button(105, 70, 120, 25, "Replace Next")
replace_cancel = fltk:Fl_Button(230, 70, 60, 25, "Cancel")

-- CALLBACKS FOR REPLACE DIALOG
replace_cancel:callback(function () replace_dlg:hide() end )

-- MAIN PROGRAM
w:show()
Fl:run()


Posted by mikshaw on Nov. 06 2007,02:43
I don't know much about the Fl_Text_* widgets at this point, but for searching strings I generally rely on Lua functions rather than FLTK.  Check the "string manipulation" section of the Lua documentation.
Posted by roberts on Nov. 06 2007,03:36
Perhaps something along the lines of:
Code Sample

   174 function find_cb()
   175    local str
   176    local fnd
   177    local startPos = 1
   178    str = fltk.fl_input("Insert a string to search", lastsearch)
   179    if (str ~= 0) then
   180 --    fnd = tb:search_forward(0,str,fnd,0)
   181       fnd,fndEnd = string.find(tb:text(),str,startPos)
   182       if (fnd ~= nil) then
   183          fnd = fnd - 1
   184          tb:select(fnd, tb:word_end(fnd))
   185       else
   186          fltk.fl_message("String " .. str .. "Not found!")
   187       end
   188    end
   189 end

Posted by mikshaw on Nov. 06 2007,04:28
another thing I forgot to mention:
Code Sample
local str
local fnd
local startPos=1

can be more simply written:
Code Sample
local startPos,str,fnd=1

Posted by mav_it on Nov. 12 2007,12:15
Thank to Mikshaw and Roberts, now the example editor works, more or less.

It uses "standard" keybindings for cut/copy/paste and delete text (ctlr+x, ctlr+C, ctrl+V and Del respctively) and the menus are working.

Posted, should someone find useful, as I have found, to learn some murgaLua basics.)

Thank you again for your help, Mauro


Code Sample

#!/bin/lua

version = "0.02"

ww = 1024
wh = 768

title = "MURGA LUA FLTK EDITOR - "

-- Main window
w = fltk:Fl_Double_Window(ww,wh,title)

-- Text Buffer to hold file to edit
tb = fltk:Fl_Text_Buffer();

changed         = false
filename        = ""
saved           = true
newfile         = false
lastsearch      = ""
startPos        = 1

-- This will be used to hold copied / cutted text
clipboard = ""

-- Editor widget will work for standard keyboard shortcuts
ed = fltk:Fl_Text_Editor(10,30,ww-20,wh-60)
ed:buffer(tb)


function ask_save(object)
   if (not saved) then
        if fltk.fl_choice("There are unsevd Buffers. Do you want to save ?","No",nil,"Yes") >= 1 then
           save_cb()
       end
   end
end

-- check if we need to save to close
function check_save(object)
   if (not saved) then
       if fltk.fl_choice("There are unsaved Buffers. Do you Really want to exit ?","No",nil,"Yes") >= 1 then
           w:hide()
       end
   else
       w:hide()
   end
end
                                                 

w:callback(check_save)

-- Callback for menu bar
function menuItem(object)
   --print(mb:text() .. ' --> ' .. mb:value())
   if  (mb:text()=="&New File") then new_cb()

       -- FILE MENU
       elseif (mb:text()=="&Open File") then open_cb()
       elseif (mb:text()=="&Insert File") then insert_cb()
       elseif (mb:text()=="&Save File") then save_cb()
       elseif (mb:text()=="Save File &As") then saveas_cb()
       elseif (mb:text()=="E&xit") then exit_cb()

       -- EDIT MENU
       elseif (mb:text()=="&Undo") then undo_cb()
       elseif (mb:text()=="Cu&t") then cut_cb()
       elseif (mb:text()=="&Copy") then copy_cb()
       elseif (mb:text()=="&Paste") then paste_cb()
       elseif (mb:text()=="&Delete") then delete_cb()

       -- SEARCH MENU
       elseif (mb:text()=="&Find...") then find_cb()
       elseif (mb:text()=="Find &Again") then findagain_cb()
       elseif (mb:text()=="&Replace...") then replace_cb()

       -- TOOLS MENU
       elseif (mb:text()=="&Insert Date") then insertdate_cb()

       -- HELP MENU
       elseif (mb:text()=="&About") then about_cb()
   end
end

-- FILE MENU CALLBACKS

function new_cb()
   ask_save()
   newfile     = true
   filename    = "untitled"
   saved       = false
   tb:remove(0,tb:length())
   w:label(title .. filename)
end

function open_cb()
   ask_save()
   filename = fltk.fl_file_chooser("Select File to open", nil, nil, 0)
   if (filename ~= nil) then
       tb:loadfile(filename)
       w:label(title .. filename)
       saved = false
   end
end

function insert_cb()
   local fname = fltk.fl_file_chooser("Select File to insert", nil, nil, 0)
   if (fname ~= nil) then
       local pos = ed:insert_position()
       tb:insertfile(fname,pos)
   end
end


function save_cb()
   if (newfile) then
       saveas_cb()
   elseif (not saved) then
       if (tb:savefile(filename)) then
           saved = true
           fltk.fl_message("File " .. filename .. " Saved.")
       else
           fltk.fl_alert("Error writing file " .. filename)
       end
   end

end

function saveas_cb()
   local fname = fltk.fl_file_chooser("FILENAME TO SAVE", nil, nil, 0)
   if (fname ~= nil) then
       if (tb:savefile(fname)) then
           filename = fname
           w:label(title .. filename)
           saved = true
           fltk.fl_message("File " .. filename .. " Saved.")
       else
           fltk.fl_alert("Error writing file " .. filename)
       end
   end
end

function close_cb()
   ask_saved()
end


function exit_cb()
   check_save()
end

-- EDIT MENU CALLBACKS
function undo_cb()
end

function cut_cb()
   if ( tb:selected() ~= 0) then
       clipboard = tb:selection_text()
       tb:remove_selection()
   end
end

function copy_cb()
   if (tb:selected() ~= 0) then
       clipboard = tb:selection_text()
   end
end

function paste_cb()
   local pos = ed:insert_position()
   tb:insert(pos,clipboard)
end

function delete_cb()
   if (tb:selected() ~= 0) then
       tb:remove_selection()
   end
end


function delete_cb()
   if (tb:selected() ~= 0) then
       tb:remove_selection()
   end
end

-- SEARCH MENU CALLBACKS
function find_cb()
   local str, fnd, fndEnd
   startPos=1
   str = fltk.fl_input("Insert a string to search", lastsearch)
   if (str ~= nil) then
       --fnd = tb:search_forward(0,str,fnd,0)
       fnd,fndEnd = string.find(tb:text(),str,startPos)
       if (fnd ~= nil) then
           tb:select(fnd-1, fndEnd)
           lastsearch = str
           startPos = fndEnd
       else
           fltk.fl_message("String '" .. str .. "' Not found!")
       end
   end

end

function findagain_cb()

   if (lastsearch == "") then
       find_cb()
   else
       fnd,fndEnd= string.find(tb:text(),lastsearch,startPos)
       if (fnd ~= nil) then
           tb:select(fnd-1, fndEnd)
           startPos = fndEnd
       else
           fltk.fl_message("String '" .. lastsearch .. "' Not found!")
           startPos=1
       end
   end
end

function replace_cb()
   replace_dlg:show()
end

-- TOOLS CALLBACKS
function insertdate_cb()
   local pos = ed:insert_position()
   local date = os.date()
   tb:insert(pos,date)
end


-- HELP CALLBACKS
function about_cb()
   fltk.fl_message("MURGA LUA FLTK EDITOR\n\nMurga Lua Version of FLTK editor example\nBy Mauro Viarizzo (mav_it)\n\nVersion " .. version)
end

--- Build Up dynamically the menu:
mb = fltk:Fl_Menu_Bar(0,0,ww,30)
mb:callback(menuItem)

mb:add("&File/&New File",       0, 0)
mb:add("&File/&Open File",      0, 0)
mb:add("&File/&Insert File",    0, 0)
mb:add("&File/&Save File",      0, 0)
mb:add("&File/Save File &As",   0, 0)
mb:add("&File/E&xit",           0, 0)


mb:add("&Edit/&Undo",           0, 0)
mb:add("&Edit/Cu&t",            0, 0)

mb:add("&Edit/&Copy",           0, 0)
mb:add("&Edit/&Paste",          0, 0)
mb:add("&Edit/&Delete",         0, 0)


mb:add("&Search/&Find...",      0, 0)
mb:add("&Search/Find &Again",   0, 0)
mb:add("&Search/&Replace...",   0, 0)

mb:add("&Tools/&Insert Date",   0, 0)

mb:add("&Help/&About",          0, 0)

--This does not seem to be implemented in MurgaLua FLTK
--tb:add_modify_callback(changed_cb, w)
--tb:call_modify_callbacks()

-- REPLACE DIALOG
replace_dlg     = fltk:Fl_Window    (420, 105, "Replace")
replace_find    = fltk:Fl_Input         ( 70, 10, 330, 25, "Find:")
replace_with    = fltk:Fl_Input         ( 70, 40, 330, 25, "Replace:")
replace_all     = fltk:Fl_Button        ( 10, 70,  90, 25, "Replace All")
replace_next    = fltk:Fl_Return_Button (105, 70, 120, 25, "Replace Next")
replace_skip    = fltk:Fl_Button        (230, 70, 120, 25, "Skip to Next")
replace_cancel  = fltk:Fl_Button        (355, 70,  60, 25, "Cancel")

replPos=1

-- CALLBACKS FOR REPLACE DIALOG
function replace_next_cb(mesg,doRepl)
   local findTxt = replace_find:value()
   local replTxt = replace_with:value()
   local fnd, fndEnd

   fnd,fndEnd = string.find(tb:text(),findTxt,replPos)
   if (fnd ~= nil) then
       if (doRepl) then
           tb:replace(fnd-1, fndEnd, replTxt)
       end
       replPos = tb:word_end(fnd)+1
       return true
   else
       if (mesg) then
           fltk.fl_message("String '" .. findTxt .. "' Not found!")
       end
       replPos = 1
       return false
   end
end

function replace_all_cb()
   local replaces = 0
   while (replace_next_cb(false, true)) do
       replaces = replaces + 1
   end
   fltk.fl_message("Replaced " .. replaces .. " occurrences")
end

function replace_skip_cb()
   replace_next_cb(true,false)
end

replace_cancel:callback(function () replace_dlg:hide() end )
replace_next:callback(function () replace_next_cb(true, true) end)
replace_skip:callback(function () replace_skip_cb() end)
replace_all:callback(function () replace_all_cb() end)


-- MAIN PROGRAM
w:show()
Fl:run()







Posted by roberts on Nov. 12 2007,16:37
Impressive! Thanks for sharing.
Posted by roberts on Nov. 23 2007,05:33
I added a few simple changes, started it at 800x600 and made it resizable, added support for command line arguments, which allows drag-n-drop. Going to add it to DSL as our simple notepad.
Posted by mav_it on Nov. 24 2007,14:20
Wow ! Tank You!

How do you make the windows resizable in murgaLua ? I have read documentation but didn't get how to to it.

Cheers, Mauro

Posted by roberts on Nov. 24 2007,14:30
Mauro, Thank you for your efforts and sharing.

Like I said it is very impressive.
These are the simple changes I added.

    11 -- Main window
    12 w = fltk:Fl_Double_Window(ww,wh,title)
    13 w:resizable(w)

------------------
   324 -- MAIN PROGRAM
   325 if #arg == 1 then
   326    filename = arg[1]
   327    tb:loadfile(filename)
   328    w:label(title .. filename)
   329    saved=false
   330 end

   331 w:show()
   332 Fl:run()



Powered by Ikonboard 3.1.2a
Ikonboard © 2001 Jarvis Entertainment Group, Inc.