-- here is a complete sample file of lua code
--------------------------------------------------------------------------------
----------
-- globals
--------------------------------------------------------------------------------
----------
local appName="wxSME"
local appFile
local appDocument={filePath="",fileName="",modTime={},isModified=false}
local frame --parent window
local editor --edit surface
local menu --main menu
-- ASCII values for common chars
local char_CR = string.byte("\r")
local char_LF = string.byte("\n")
local char_Tab = string.byte("\t")
local char_Sp = string.byte(" ")
local font = nil
local fontItalic = nil
if wx.__WINDOWS__ then ---windows
appFile = appName..".exe"
font = wx.wxFont(8,
wx.wxFONTFAMILY_MODERN,
wx.wxFONTSTYLE_NORMAL,
wx.wxFONTWEIGHT_NORMAL,
false, "Lucida Console")
fontItalic = wx.wxFont(8,
wx.wxFONTFAMILY_MODERN,
wx.wxFONTSTYLE_ITALIC,
wx.wxFONTWEIGHT_NORMAL,
false, "Lucida Console")
else --- mac then??
appFile = appName..".app"
font = wx.wxFont(12,
wx.wxFONTFAMILY_MODERN,
wx.wxFONTSTYLE_NORMAL,
wx.wxFONTWEIGHT_NORMAL,
false, "")
fontItalic = wx.wxFont(12,
wx.wxFONTFAMILY_MODERN,
wx.wxFONTSTYLE_ITALIC,
wx.wxFONTWEIGHT_NORMAL,
false, "")
end
local ID_IDCOUNTER = wx.wxID_HIGHEST + 1
--------------------------------------------------------------------------------
----------
-- helper functions
--------------------------------------------------------------------------------
----------
-- Generate a unique new wxWindowID
function NewID()
ID_IDCOUNTER = ID_IDCOUNTER + 1
return ID_IDCOUNTER
end
function HasBit(value, num)
for n = 32, 0, -1 do
local b = 2^n
local num_b = num - b
local value_b = value - b
if num_b >= 0 then
num = num_b
else
return true -- already tested bits in num
end
if value_b >= 0 then
value = value_b
end
if (num_b >= 0) and (value_b < 0) then
return false
end
end
return true
end
function GetFileModTime(filePath)
if filePath and (string.len(filePath) > 0) then
local fn = wx.wxFileName(filePath)
if fn:FileExists() then
return fn:GetModificationTime()
end
end
return nil
end
-- Equivalent to C's "cond ? a : b", all terms will be evaluated
function iff(cond, a, b) if cond then return a else return b end end
-- Start a program
function run(filePath)
return wx.wxProcess.Open(filePath, wx.wxEXEC_NOHIDE+wx.wxEXEC_ASYNC)
end
--------------------------------------------------------------------------------
----------
-- frame
--------------------------------------------------------------------------------
----------
frame = wx.wxFrame(
wx.NULL,
wx.wxID_ANY,
appName,
wx.wxDefaultPosition,
wx.wxSize(800,700),
wx.wxDEFAULT_FRAME_STYLE
)
--------------------------------------------------------------------------------
----------
-- menu
--------------------------------------------------------------------------------
----------
-- File menu
local ID_NEW = wx.wxID_NEW
local ID_OPEN = wx.wxID_OPEN
local ID_BROWSE = NewID()
local ID_SAVE = wx.wxID_SAVE
local ID_SAVEAS = wx.wxID_SAVEAS
local ID_EXIT = wx.wxID_EXIT
-- Edit menu
local ID_UNDO = wx.wxID_UNDO
local ID_REDO = wx.wxID_REDO
local ID_CUT = wx.wxID_CUT
local ID_COPY = wx.wxID_COPY
local ID_PASTE = wx.wxID_PASTE
local ID_DELETE = wx.wxID_DELETE
local ID_SELECTALL = wx.wxID_SELECTALL
local ID_FIND = wx.wxID_FIND
local ID_REPLACE = NewID()
local ID_UPPER = NewID()
local ID_LOWER = NewID()
local ID_INDENT = NewID()
local ID_UNINDENT = NewID()
-- View menu
local ID_WRAP = NewID()
local ID_FOLD= NewID()
local ID_UNFOLD = NewID()
-- Help menu
local ID_ABOUT = wx.wxID_ABOUT
function CreateMenu()
menuBar = wx.wxMenuBar()
fileMenu = wx.wxMenu({
{ ID_NEW, "&New\tCtrl-N", "Create a new window" },
{ },
{ ID_OPEN, "&Open...\tCtrl-O", "Open an existing script" },
{ ID_SAVE, "&Save\tCtrl-S", "Save the current script" },
{ ID_SAVEAS, "Save &As...\tCtrl-D", "Save the current script to a file
with a new name" },
{ ID_BROWSE, "&Browse To\tCtrl-B", "Open the current script in a
browser" },
{ },
{ ID_EXIT, "&Quit\tCtrl-Q", "Quit "..appName }})
menuBar:Append(fileMenu, "&File")
editMenu = wx.wxMenu{
{ ID_UNDO, "&Undo\tCtrl-Z", "Undo the last action" },
{ ID_REDO, "&Redo\tCtrl-Y", "Redo the last action undone" },
{ },
{ ID_CUT, "Cu&t\tCtrl-X", "Cut selected text to clipboard"
},
{ ID_COPY, "&Copy\tCtrl-C", "Copy selected text to the
clipboard" },
{ ID_PASTE, "&Paste\tCtrl-V", "Insert clipboard text at cursor"
},
{ ID_DELETE, "Delete\tDelete", "Delete selected text" },
{ },
{ ID_SELECTALL, "Select A&ll\tCtrl-A", "Select all text in the editor"
},
{ },
{ ID_FIND, "&Find\tCtrl-F", "Find the specified text" },
{ ID_REPLACE, "&Replace\tCtrl-R", "Replaces the specified
text with different text" },
{ },
{ ID_UPPER, "&Upper Case\tCtrl-U", "Change selected text to
upper case" },
{ ID_LOWER, "&Lower Case\tCtrl-L", "Change selected text to
lower case" },
{ },
{ ID_INDENT, "&Indent\tTab", "Indent the selected text" },
{ ID_UNINDENT, "&Unindent\tShift-Tab", "Unindent the selected
text" }
}
menuBar:Append(editMenu, "&Edit")
viewMenu = wx.wxMenu{
{ ID_WRAP, "&Word Wrap\tCtrl-W", "Toggle word wrap" },
{ },
{ ID_FOLD, "&Fold All\tCtrl-1", "Folds all nodes" },
{ ID_UNFOLD, "&Unfold All\tCtrl-2", "Unfolds all nodes" }
}
menuBar:Append(viewMenu, "&View")
helpMenu = wx.wxMenu{
{ ID_ABOUT, "&About\t", "About "..appName },
}
menuBar:Append(helpMenu, "&Help")
frame:SetMenuBar(menuBar)
return menuBar
end
--------------------------------------------------------------------------------
----------
-- editor
--------------------------------------------------------------------------------
----------
function CreateEditor(name)
local editor = wxstc.wxStyledTextCtrl(frame, 1010,
wx.wxDefaultPosition, wx.wxDefaultSize
,
wx.wxSUNKEN_BORDER)
editor:SetBufferedDraw(true)
editor:StyleClearAll()
editor:SetStyling(0, 0);
editor:SetStyleBits(8)
editor:SetLexer(wxstc.wxSTC_LEX_HTML)
editor:SetFont(font)
editor:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, font)
for i = 0, 127 do
editor:StyleSetFont(i, font)
end
------- HTML Styles
editor:StyleSetForeground(0, wx.wxColour(0, 0, 0)) -- Default
editor:StyleSetForeground(1, wx.wxColour(0, 0, 255)) -- Tag
editor:StyleSetForeground(2, wx.wxColour(0, 0, 255)) -- Tag Unknown
editor:StyleSetForeground(3, wx.wxColour(127, 179, 255)) -- Attribute
editor:StyleSetForeground(5, wx.wxColour(0,179, 179)) -- Number (width=4)
editor:StyleSetForeground(6, wx.wxColour(0,179, 179)) -- Double quoted
string (width="4")
editor:StyleSetForeground(7, wx.wxColour(0, 179, 179)) -- Single quoted
string (width='4')
editor:StyleSetForeground(8, wx.wxColour(127, 179, 255)) -- Other (=)
editor:StyleSetForeground(9, wx.wxColour(179, 179, 179)) -- Comment
<!-- hi -->
editor:StyleSetForeground(10, wx.wxColour(0, 127, 0)) -- Entity
( )
------- XML Styles
editor:StyleSetForeground(12, wx.wxColour(0, 0, 255)) -- XML Start (<?)
editor:StyleSetForeground(13, wx.wxColour(0, 0, 255)) -- XML End (?>)
editor:StyleSetForeground(14, wx.wxColour(255, 0, 0)) -- Script
editor:StyleSetForeground(15, wx.wxColour(255, 0, 0)) -- ASP
editor:StyleSetForeground(16, wx.wxColour(255, 0, 0)) -- ASPAT
editor:StyleSetForeground(17, wx.wxColour(255, 0, 0)) -- CDATA
editor:StyleSetForeground(18, wx.wxColour(0, 0, 255)) -- Question
------- SGML Styles
editor:StyleSetForeground(21, wx.wxColour(179, 0, 0)) -- SGML_DEFAULT
editor:StyleSetForeground(24, wx.wxColour(179, 0, 0)) --
SGML_DOUBLESTRING
editor:StyleSetForeground(25, wx.wxColour(179, 0, 0)) --
SGML_SIMPLESTRING
editor:StyleSetForeground(26, wx.wxColour(179, 0, 0)) -- SGML_ERROR
------- JavaScript Styles
editor:StyleSetForeground(41, wx.wxColour(0, 0, 0 )) -- JS Default
editor:StyleSetForeground(42, wx.wxColour(179, 179, 179)) -- JS
comment
editor:StyleSetForeground(43, wx.wxColour(179, 179, 179)) -- JS comment
Line
editor:StyleSetForeground(44, wx.wxColour(179, 179, 179)) -- JS comment
DOC
editor:StyleSetForeground(45, wx.wxColour(0, 0, 255)) -- JS number
editor:StyleSetForeground(46, wx.wxColour(0, 0, 0)) -- JS word
editor:StyleSetForeground(47, wx.wxColour(0, 0, 255)) -- JS keyword
editor:StyleSetForeground(48, wx.wxColour(127, 0, 127)) -- JS double
string
editor:StyleSetForeground(49, wx.wxColour(127, 0, 127)) -- JS single
string
editor:StyleSetForeground(52, wx.wxColour(179, 0, 0)) -- JS regex
------- PHP Styles
editor:StyleSetForeground(118, wx.wxColour(0, 0, 0 )) -- PHP Default
editor:StyleSetForeground(119, wx.wxColour(127, 0, 127)) -- PHP
hstring
editor:StyleSetForeground(120, wx.wxColour(127, 0, 127)) -- PHP
simplestring
editor:StyleSetForeground(121, wx.wxColour(0, 0, 255)) -- PHP word
editor:StyleSetForeground(122, wx.wxColour(0, 0, 255)) -- PHP number
editor:StyleSetForeground(123, wx.wxColour(0, 127, 0)) -- PHP $var
editor:StyleSetForeground(124, wx.wxColour(179, 179, 179)) -- PHP
Comment
editor:StyleSetForeground(125, wx.wxColour(179, 179, 179)) -- PHP
Comment Line
editor:StyleSetForeground(126, wx.wxColour(0, 127, 0)) -- PHP hstring
$var
editor:StyleSetForeground(127, wx.wxColour(0, 0, 0)) -- PHP operator
for i=118,127 do
editor:StyleSetEOLFilled(i, true)
editor:StyleSetBackground(i, wx.wxColour(249, 251, 249 ))
end
------- GUI Styles
editor:StyleSetForeground(32, wx.wxColour(240, 220, 240)) -- Fold Line
editor:StyleSetForeground(33, wx.wxColour(140,140, 140)) -- Line no.s
editor:StyleSetForeground(36, wx.wxColour(255, 0, 0)) -- Control char
(these shouldnt show up)
editor:StyleSetForeground(37, wx.wxColour(220, 220, 220)) -- indent guides
editor:SetUseTabs(true)
editor:SetTabWidth(4)
editor:SetIndent(4)
editor:SetIndentationGuides(true)
editor:SetVisiblePolicy(wxstc.wxSTC_VISIBLE_SLOP, 3)
editor:SetMarginWidth(0, editor:TextWidth(32, "99999")) -- line no width
editor:SetMarginWidth(1, 4) -- line no margin
editor:SetMarginType(1, wxstc.wxSTC_MARGIN_SYMBOL)
editor:SetMarginSensitive(1, true)
editor:SetMarginWidth(2, 16) -- fold margin
editor:SetMarginType(2, wxstc.wxSTC_MARGIN_SYMBOL)
editor:SetMarginMask(2, wxstc.wxSTC_MASK_FOLDERS)
editor:SetMarginSensitive(2, true)
editor:SetProperty("fold", "1")
editor:SetProperty("fold.html", "1")
editor:SetProperty("fold.compact", "1")
editor:SetProperty("fold.comment", "1")
local grey = wx.wxColour(179, 179, 179)
editor:MarkerDefine(
wxstc.wxSTC_MARKNUM_FOLDEROPEN,
wxstc.wxSTC_MARK_BOXMINUS,
wx.wxWHITE, grey)
editor:MarkerDefine(
wxstc.wxSTC_MARKNUM_FOLDER,
wxstc.wxSTC_MARK_BOXPLUS,
wx.wxWHITE, grey)
editor:MarkerDefine(
wxstc.wxSTC_MARKNUM_FOLDERSUB,
wxstc.wxSTC_MARK_VLINE,
wx.wxWHITE, grey)
editor:MarkerDefine(
wxstc.wxSTC_MARKNUM_FOLDERTAIL,
wxstc.wxSTC_MARK_LCORNER,
wx.wxWHITE, grey)
editor:MarkerDefine(
wxstc.wxSTC_MARKNUM_FOLDEREND,
wxstc.wxSTC_MARK_BOXPLUSCONNECTED,
wx.wxWHITE, grey)
editor:MarkerDefine(
wxstc.wxSTC_MARKNUM_FOLDEROPENMID,
wxstc.wxSTC_MARK_BOXMINUSCONNECTED,
wx.wxWHITE, grey)
editor:MarkerDefine(
wxstc.wxSTC_MARKNUM_FOLDERMIDTAIL,
wxstc.wxSTC_MARK_TCORNER,
wx.wxWHITE, grey)
grey:delete()
--- HTML tags
----- if active then tags not in this list would show up under the "Tag
Unknown" style
----- however with the x* flavor of markup languages this seems
outdated...
if onlyHTML then
editor:SetKeyWords(0,
[[a b body br center cite code col colgroup dd dfn div dl dt em font
form frame frameset
h1 h2 h3 h4 h5 h6 head hr html i iframe img input kbd li link map meta
noframes noscript
object ol optgroup option p param pre q s samp script select small span
strong style sub
sup table tbody td textarea tfoot th thead title tr tt u ul]])
end
---js keywords (reserved words, base functions and document methods)
editor:SetKeyWords(1,
[[abstract boolean break byte case catch char class const continue
debugger default delete
do double else enum export extends false final finally float for
function goto if implements
import in instanceof int interface long native new null package private
protected public return
short static super switch synchronized this throw throws transient true
try typeof var void
volatile while with alert Array Date decodeURI decodeURIComponent
encodeURI
encodeURIComponent escape eval Infinity isFinite isFinite NaN Number
Object parseFloat
parseInt String undefined unescape document.anchors document.forms
document.images
document.links document.cookie document.close document.domain
document.getElementById
document.getElementsByName document.getElementsByTagName document.open
document.write document.writeIn document.lastModified document.referrer
document.title
document.URL]])
-----php keywords (reserved words and common base functions)
editor:SetKeyWords(4,
[[addcslashes addslashes and array array_chunk array_combine
array_count_values array_diff
array_fill array_flip array_intersect array_keys array_key_exists
array_map array_merge
array_pad array_pop array_push array_shift array_slice array_splice
array_sum array_values
array_walk array_walk_recursive as base64_decode base64_encode break
case chdir checkdate
chgrp chmod chop chown chr chroot class closedir closelog compact const
constant continue
connection_aborted connection_status connection_timeout copy count
count_chars current date
date_create date_format debug_zval_dump declare default define defined
delete die dir dirname
display_startup_errors display_errors do docref_ext docref_root each
doubleval echo else elseif
empty end enddeclare endfor endforeach endif endswitch endwhile
error_append_string error_log
error_prepend_string error_reporting eval exception exit explode extends
extract ezmlm_hash
false fclose feof fflush file file_exists file_get_contents
file_put_contents fileatime
filectime filegroup fileinode filemtime fileowner fileperms filesize
filetype fopen for foreach
floatval fpassthru fputs fread fscanf fseek fstat ftell ftruncate fwrite
function get_browser
getcwd getdate gettype get_defined_vars get_headers get_meta_tags
get_resource_type glob global
idate header highlight_file highlight_string html_errors htmlentities
htmlspecialchars
htmlspecialchars_ decode http_build_query if import implode
request_variables ignore_repeated_errors
ignore_repeated_source implode intval in_array include include_once
isset is_array is_binary
is_bool is_buffer is_callable is_double is_dir is_executable is_float
is_file is_int is_integer
is_link is_long is_null is_numeric is_object is_readable is_real
is_resource is_scalar is_string
is_unicodeis_uploaded_file is_writable is_writeable join key link
linkinfo list localtime
log_errors log_errors_max_len lstat mail mkdir mktime move_uploaded_file
new NULL opendir openlog or
ord pack parse_ini_file parse_url pathinfo pclose popen php_check_syntax
php_strip_whitespace pos
preg_grep preg_last_error preg_match_all preg_match preg_quote
preg_replace_ callback preg_replace
preg_split prev print printf print_r private public range rawurldecode
rawurlencode readdir
report_memleaks readfile readlink realpath rename rewind require
require_once reset return rewinddir
rmdir rtrim scandir serialize setcookie setrawcookie settype show_source
sizeof sleep split stat
static strchr str_ireplace str_replace strcmp strcoll stripcslashes
stripslashes stristr strlen
strpos strstr strtok strtotime strval substr substr_compare substr_count
substr_replace switch
symlink syslog tempnam time tmpfile touch track_errors trim true umask
uniqid unlink unpack
unserialize unset use urldecode urlencode usleep var var_dump var_export
vfprintf vprintf
vsprintf while xor]])
---code fold
editor:Connect(wxstc.wxEVT_STC_MARGINCLICK,
function (event)
if event:GetMargin() == 2 then
local line = editor:LineFromPosition(event:GetPosition())
local level = editor:GetFoldLevel(line)
if HasBit(level, wxstc.wxSTC_FOLDLEVELHEADERFLAG) then
editor:ToggleFold(line)
end
end
end)
editor:Connect(wxstc.wxEVT_STC_CHARADDED,
function (event)
appDocument.isModified=true
-- auto-indent
local ch = event:GetKey()
if (ch == char_CR) or (ch == char_LF) then
local pos = editor:GetCurrentPos()
local line = editor:LineFromPosition(pos)
local indent = editor:GetLineIndentation(line-1)
editor:SetLineIndentation(line,indent)
pos=editor:GetLineIndentPosition(line)
editor:GotoPos(pos)
end
end)
return editor
end
--------------------------------------------------------------------------------
----------
-- find/replace
--------------------------------------------------------------------------------
----------
findReplace = {
dialog = nil, -- the wxDialog for find/replace
replace = false, -- is it a find or replace dialog
fWholeWord = false, -- match whole words
fMatchCase = false, -- case sensitive
fDown = true, -- search downwards in doc
fRegularExpr = false, -- use regex
fWrap = false, -- search wraps around
findTextArray = {}, -- array of last entered find text
findText = "", -- string to find
replaceTextArray = {}, -- array of last entered replace text
replaceText = "", -- string to replace find string with
foundString = false, -- was the string found for the last search
}
function EnsureRangeVisible(posStart, posEnd)
if posStart > posEnd then
posStart, posEnd = posEnd, posStart
end
local lineStart = editor:LineFromPosition(posStart)
local lineEnd = editor:LineFromPosition(posEnd)
for line = lineStart, lineEnd do
editor:EnsureVisibleEnforcePolicy(line)
end
end
function SetSearchFlags()
local flags = 0
if findReplace.fWholeWord then flags = wxstc.wxSTC_FIND_WHOLEWORD end
if findReplace.fMatchCase then flags = flags + wxstc.wxSTC_FIND_MATCHCASE
end
if findReplace.fRegularExpr then flags = flags + wxstc.wxSTC_FIND_REGEXP
end
editor:SetSearchFlags(flags)
end
function SetTarget(fDown, fInclude)
local selStart = editor:GetSelectionStart()
local selEnd = editor:GetSelectionEnd()
local len = editor:GetLength()
local s, e
if fDown then
e= len
s = iff(fInclude, selStart, selEnd +1)
else
s = 0
e = iff(fInclude, selEnd, selStart-1)
end
if not fDown and not fInclude then s, e = e, s end
editor:SetTargetStart(s)
editor:SetTargetEnd(e)
return e
end
function findReplace:HasText()
return (findReplace.findText ~= nil) and (string.len(findReplace.findText) >
0)
end
function findReplace:GetSelectedString()
local startSel = editor:GetSelectionStart()
local endSel = editor:GetSelectionEnd()
if (startSel ~= endSel)
and (editor:LineFromPosition(startSel) == editor:LineFromPosition(endSel))
then
findReplace.findText = editor:GetSelectedText()
findReplace.foundString = true
end
end
function findReplace:FindString(reverse)
if findReplace:HasText() then
local fDown = iff(reverse, not findReplace.fDown, findReplace.fDown)
local lenFind = string.len(findReplace.findText)
SetSearchFlags()
SetTarget(fDown)
local posFind = editor:SearchInTarget(findReplace.findText)
if (posFind == -1) and findReplace.fWrap then
editor:SetTargetStart(iff(fDown, 0, editor:GetLength()))
editor:SetTargetEnd(iff(fDown, editor:GetLength(), 0))
posFind = editor:SearchInTarget(findReplace.findText)
end
if posFind == -1 then
findReplace.foundString = false
frame:SetStatusText("Find text not found.")
else
findReplace.foundString = true
local start = editor:GetTargetStart()
local finish = editor:GetTargetEnd()
EnsureRangeVisible(start, finish)
editor:SetSelection(start, finish)
end
end
end
function ReplaceString(fReplaceAll)
if findReplace:HasText() then
local replaceLen = string.len(findReplace.replaceText)
local findLen = string.len(findReplace.findText)
local endTarget = SetTarget(findReplace.fDown, fReplaceAll)
if fReplaceAll then
SetSearchFlags()
local posFind = editor:SearchInTarget(findReplace.findText)
if (posFind ~= -1) then
editor:BeginUndoAction()
while posFind ~= -1 do
editor:ReplaceTarget(findReplace.replaceText)
editor:SetTargetStart(posFind + replaceLen)
endTarget = endTarget + replaceLen - findLen
editor:SetTargetEnd(endTarget)
posFind = editor:SearchInTarget(findReplace.findText)
end
editor:EndUndoAction()
end
else
if findReplace.foundString then
local start = editor:GetSelectionStart()
editor:ReplaceSelection(findReplace.replaceText)
editor:SetSelection(start, start + replaceLen)
findReplace.foundString = false
end
findReplace:FindString()
end
end
end
function CreateFindReplaceDialog(replace)
local ID_FIND_NEXT = 1
local ID_REPLACE = 2
local ID_REPLACE_ALL = 3
findReplace.replace = replace
local findDialog = wx.wxDialog(frame, wx.wxID_ANY, "Find/Replace",
wx.wxDefaultPosition, wx.wxDefaultSize)
-- Create right hand buttons and sizer
local findButton = wx.wxButton(findDialog, ID_FIND_NEXT, "&Find Next")
findButton:SetDefault()
local replaceButton = wx.wxButton(findDialog, ID_REPLACE, "&Replace")
local replaceAllButton = nil
if (replace) then
replaceAllButton = wx.wxButton(findDialog, ID_REPLACE_ALL, "Replace
&All")
end
local cancelButton = wx.wxButton(findDialog, wx.wxID_CANCEL, "Cancel")
local buttonsSizer = wx.wxBoxSizer(wx.wxVERTICAL)
buttonsSizer:Add(findButton, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 3)
buttonsSizer:Add(replaceButton, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 3)
if replace then
buttonsSizer:Add(replaceAllButton, 0, wx.wxALL + wx.wxGROW +
wx.wxCENTER, 3)
end
buttonsSizer:Add(cancelButton, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 3)
-- Create find/replace text entry sizer
local findStatText = wx.wxStaticText( findDialog, wx.wxID_ANY, "Find: ")
local findTextCombo = wx.wxTextCtrl (findDialog, wx.wxID_ANY,
findReplace.findText, wx.wxDefaultPosition, wx.wxDefaultSize)
findTextCombo:SetFocus()
local replaceStatText, replaceTextCombo
if (replace) then
replaceStatText = wx.wxStaticText( findDialog, wx.wxID_ANY, "Replace:
")
replaceTextCombo = wx.wxTextCtrl(findDialog, wx.wxID_ANY,
findReplace.replaceText, wx.wxDefaultPosition, wx.wxDefaultSize)
end
local findReplaceSizer = wx.wxFlexGridSizer(2, 2, 0, 0)
findReplaceSizer:AddGrowableCol(1)
findReplaceSizer:Add(findStatText, 0, wx.wxALL + wx.wxALIGN_LEFT, 0)
findReplaceSizer:Add(findTextCombo, 1, wx.wxALL + wx.wxGROW + wx.wxCENTER,
0)
if (replace) then
findReplaceSizer:Add(replaceStatText, 0, wx.wxTOP + wx.wxALIGN_CENTER,
5)
findReplaceSizer:Add(replaceTextCombo, 1, wx.wxTOP + wx.wxGROW +
wx.wxCENTER, 5)
end
-- Create find/replace option checkboxes
local wholeWordCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Match
&whole word")
local matchCaseCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Match
&case")
local wrapAroundCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Wrap
ar&ound")
local regexCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Regular
&expression")
wholeWordCheckBox:SetValue(findReplace.fWholeWord)
matchCaseCheckBox:SetValue(findReplace.fMatchCase)
wrapAroundCheckBox:SetValue(findReplace.fWrap)
regexCheckBox:SetValue(findReplace.fRegularExpr)
local optionSizer = wx.wxBoxSizer(wx.wxVERTICAL, findDialog)
optionSizer:Add(wholeWordCheckBox, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER,
3)
optionSizer:Add(matchCaseCheckBox, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER,
3)
optionSizer:Add(wrapAroundCheckBox, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER,
3)
optionSizer:Add(regexCheckBox, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER,
3)
local optionsSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog,
"Options" );
optionsSizer:Add(optionSizer, 0, 0, 5)
-- Create scope radiobox
local scopeRadioBox = wx.wxRadioBox(findDialog, wx.wxID_ANY, "Scope",
wx.wxDefaultPosition, wx.wxDefaultSize, {"&Up", "&Down"}, 1,
wx.wxRA_SPECIFY_COLS)
scopeRadioBox:SetSelection(iff(findReplace.fDown, 1, 0))
local scopeSizer = wx.wxBoxSizer(wx.wxVERTICAL, findDialog );
scopeSizer:Add(scopeRadioBox, 0, 0, 0)
-- Add all the sizers to the dialog
local optionScopeSizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
optionScopeSizer:Add(optionsSizer, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER,
5)
optionScopeSizer:Add(scopeSizer, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER,
5)
local leftSizer = wx.wxBoxSizer(wx.wxVERTICAL)
leftSizer:Add(findReplaceSizer, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 0)
leftSizer:Add(optionScopeSizer, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 0)
local mainSizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
mainSizer:Add(leftSizer, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 10)
mainSizer:Add(buttonsSizer, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 10)
mainSizer:SetSizeHints( findDialog )
findDialog:SetSizer(mainSizer)
local function PrependToArray(t, s)
if string.len(s) == 0 then return end
for i, v in ipairs(t) do
if v == s then
table.remove(t, i) -- remove old copy
break
end
end
table.insert(t, 1, s)
if #t > 15 then table.remove(t, #t) end -- keep reasonable length
end
local function TransferDataFromWindow()
findReplace.fWholeWord = wholeWordCheckBox:GetValue()
findReplace.fMatchCase = matchCaseCheckBox:GetValue()
findReplace.fWrap = wrapAroundCheckBox:GetValue()
findReplace.fDown = scopeRadioBox:GetSelection() == 1
findReplace.fRegularExpr = regexCheckBox:GetValue()
findReplace.findText = findTextCombo:GetValue()
PrependToArray(findReplace.findTextArray, findReplace.findText)
if findReplace.replace then
findReplace.replaceText = replaceTextCombo:GetValue()
PrependToArray(findReplace.replaceTextArray,
findReplace.replaceText)
end
return true
end
findDialog:Connect(ID_FIND_NEXT, wx.wxEVT_COMMAND_BUTTON_CLICKED,
function(event)
TransferDataFromWindow()
findReplace:FindString()
end)
findDialog:Connect(ID_REPLACE, wx.wxEVT_COMMAND_BUTTON_CLICKED,
function(event)
TransferDataFromWindow()
event:Skip()
if findReplace.replace then
ReplaceString()
else
findReplace.dialog:Destroy()
findReplace.dialog = CreateFindReplaceDialog(true)
findReplace.dialog:Show(true)
end
end)
if replace then
findDialog:Connect(ID_REPLACE_ALL, wx.wxEVT_COMMAND_BUTTON_CLICKED,
function(event)
TransferDataFromWindow()
event:Skip()
ReplaceString(true)
end)
end
findDialog:Connect(wx.wxID_ANY, wx.wxEVT_CLOSE_WINDOW,
function (event)
TransferDataFromWindow()
event:Skip()
findDialog:Show(false)
findDialog:Destroy()
end)
return findDialog
end
function findReplace:Show(replace)
self.dialog = nil
self.dialog = CreateFindReplaceDialog(replace)
self.dialog:Show(true)
end
--------------------------------------------------------------------------------
----------
-- file sys
--------------------------------------------------------------------------------
----------
function LoadFile(filePath, file_must_exist)
local file_text = ""
local handle = io.open(filePath, "rb")
if handle then
file_text = handle:read("*a")
handle:close()
elseif file_must_exist then
return nil
end
editor:Clear()
editor:ClearAll()
editor:AppendText(file_text)
editor:EmptyUndoBuffer()
appDocument.filePath = filePath
appDocument.fileName = wx.wxFileName(filePath):GetFullName()
appDocument.modTime = GetFileModTime(filePath)
appDocument.isModified = false
return true
end
function OpenFile()
local fileDialog = wx.wxFileDialog(frame, "Open file","","", "All files
(*)|*",
wx.wxOPEN + wx.wxFILE_MUST_EXIST)
if fileDialog:ShowModal() == wx.wxID_OK then
if not LoadFile(fileDialog:GetPath(), true) then
wx.wxMessageBox("Unable to load file
'"..fileDialog:GetPath().."'.",
"Error Loading",wx.wxOK + wx.wxCENTRE, frame)
else
frame:SetTitle(fileDialog:GetPath())
end
end
fileDialog:Destroy()
end
function SaveFile(filePath)
if filePath == "" then
return SaveFileAs(editor)
else
local backPath = filePath..".bak"
os.remove(backPath)
os.rename(filePath, backPath)
local handle = io.open(filePath, "wb")
if handle then
local st = editor:GetText()
handle:write(st)
handle:close()
----editor:EmptyUndoBuffer() --I hate when they do that
appDocument.filePath = filePath
appDocument.fileName = wx.wxFileName(filePath):GetFullName()
appDocument.modTime = GetFileModTime(filePath)
appDocument.isModified = false
return true
else
wx.wxMessageBox("Unable to save file '"..filePath.."'.",
"Error Saving",
wx.wxOK + wx.wxCENTRE, frame)
end
end
return false
end
function SaveFileAs()
local saved = false
local fn = wx.wxFileName(appDocument.filePath)
fn:Normalize() -- want absolute path for dialog
local fileDialog = wx.wxFileDialog(frame, "Save file as",
fn:GetPath(),
fn:GetFullName(),
"All files (*)|*",
wx.wxSAVE)
if fileDialog:ShowModal() == wx.wxID_OK then
local filePath = fileDialog:GetPath()
if SaveFile(filePath) then
saved = true
frame:SetTitle(filePath)
end
end
fileDialog:Destroy()
return saved
end
function SaveOnExit()
local result = wx.wxID_NO
local filePath = appDocument.filePath
local fileName = appDocument.fileName
if appDocument.isModified then
local message
if fileName ~= "" then
message = "Save changes to '"..fileName.."' before exiting?"
else
message = "Save changes to 'untitled' before exiting?"
end
local dlg_styles = wx.wxYES_NO + wx.wxCENTRE + wx.wxICON_QUESTION
local dialog = wx.wxMessageDialog(frame, message,"Save
Changes?",dlg_styles)
result = dialog:ShowModal()
dialog:Destroy()
if result == wx.wxID_YES then
SaveFile(filePath)
end
end
end
--------------------------------------------------------------------------------
----------
-- view
--------------------------------------------------------------------------------
----------
function Wrap()
if editor:GetWrapMode() == 1 then
editor:SetWrapMode(0)
else
editor:SetWrapMode(1)
end
end
function Fold(show)
local ss = ""
for line=0, editor.LineCount-1 do
local p = editor:GetFoldParent(line)
if p ~= -1 then
if show then
if not editor:GetFoldExpanded(p) then editor:ToggleFold(p)
end
else
if editor:GetFoldExpanded(p) then editor:ToggleFold(p) end
end
end
end
end
--------------------------------------------------------------------------------
----------
-- help
--------------------------------------------------------------------------------
----------
function About()
local dialog = wx.wxMessageDialog(frame,
appName.." is a simple editor for markup languages
developed with wxLua.",
"About",
wx.wxOK)
result = dialog:ShowModal()
dialog:Destroy()
end
--------------------------------------------------------------------------------
----------
-- init
--------------------------------------------------------------------------------
----------
frame:Connect(ID_NEW, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
run(appFile) end)
frame:Connect(ID_OPEN, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
OpenFile() end)
frame:Connect(ID_SAVE, wx.wxEVT_COMMAND_MENU_SELECTED,function(event)
SaveFile(appDocument.filePath) end)
frame:Connect(ID_SAVEAS, wx.wxEVT_COMMAND_MENU_SELECTED,function(event)
SaveFileAs() end)
frame:Connect(ID_BROWSE, wx.wxEVT_COMMAND_MENU_SELECTED,function(event)
wx.wxLaunchDefaultBrowser(appDocument.filePath) end)
frame:Connect(ID_EXIT, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
frame:Close() end)
frame:Connect(ID_CUT, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
editor:Cut() end)
frame:Connect(ID_COPY, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
editor:Copy() end)
frame:Connect(ID_PASTE, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
editor:Paste() end)
frame:Connect(ID_DELETE, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
editor:Clear() end)
frame:Connect(ID_SELECTALL, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
editor:SelectAll() end)
frame:Connect(ID_FIND, wx.wxEVT_COMMAND_MENU_SELECTED, function (event)
findReplace:Show(false) end)
frame:Connect(ID_REPLACE, wx.wxEVT_COMMAND_MENU_SELECTED, function (event)
findReplace:Show(true) end)
frame:Connect(ID_UPPER, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
editor:UpperCase() end)
frame:Connect(ID_LOWER, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
editor:LowerCase() end)
frame:Connect(ID_INDENT, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
editor:Tab() end)
frame:Connect(ID_UNINDENT, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
editor:BackTab() end)
frame:Connect(ID_UNDO, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
editor:Undo() end)
frame:Connect(ID_REDO, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
editor:Redo() end)
frame:Connect(ID_WRAP, wx.wxEVT_COMMAND_MENU_SELECTED, function(event) Wrap()
end)
frame:Connect(ID_FOLD, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
Fold(false) end)
frame:Connect(ID_UNFOLD, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
Fold(true) end)
frame:Connect(ID_ABOUT, wx.wxEVT_COMMAND_MENU_SELECTED, function(event) About()
end)
frame:Connect(wx.wxEVT_CLOSE_WINDOW, function(event) SaveOnExit();
event:Skip() end)
menu=CreateMenu()
editor=CreateEditor()
frame:Show(true)
--wx.wxGetApp():MainLoop()
-- Call wx.wxGetApp():MainLoop() last to start the wxWidgets event loop,
-- otherwise the wxLua program will exit immediately.
-- Does nothing if running from wxLua, wxLuaFreeze, or wxLuaEdit since the
-- MainLoop is already running or will be started by the C++ program.
--
<http://forum.pspad.com/read.php?2,51615,51632>
PSPad freeware editor http://www.pspad.com