mirror of
https://github.com/fltk/fltk.git
synced 2026-02-06 00:01:57 +08:00
Added Fl_Simple_Terminal widget, and mods to test+example programs (STR #3411).
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12506 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
199
FL/Fl_Simple_Terminal.H
Normal file
199
FL/Fl_Simple_Terminal.H
Normal file
@@ -0,0 +1,199 @@
|
||||
//
|
||||
// "$Id$"
|
||||
//
|
||||
// A simple terminal widget for Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2011 by Bill Spitzak and others.
|
||||
// Copyright 2017 by Greg Ercolano.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
/* \file
|
||||
Fl_Simple_Terminal widget . */
|
||||
|
||||
#ifndef Fl_Simple_Terminal_H
|
||||
#define Fl_Simple_Terminal_H
|
||||
|
||||
#include "Fl_Export.H"
|
||||
#include <FL/Fl_Text_Display.H>
|
||||
|
||||
/**
|
||||
This is a continuous text scroll widget for logging and debugging
|
||||
output, much like a terminal. Includes printf() for appending messages,
|
||||
a line limit for the screen history size, ANSI sequences to control
|
||||
text color, font face, font weight and font size.
|
||||
|
||||
This is useful in place of using stdout/stderr for logging messages
|
||||
when no terminal is available, such as when an application is invoked
|
||||
from a desktop shortcut, dock, or file browser.
|
||||
|
||||
Like a regular console terminal, the vertical scrollbar 'tracks'
|
||||
the bottom of the buffer as new output is added. If the user scrolls
|
||||
away from the bottom, this 'tracking' feature is temporarily suspended,
|
||||
so the user can browse the terminal history without fighting the scrollbar
|
||||
when new text is added asynchronously. When the user returns the
|
||||
scroller to the bottom of the display, the scrollbar's tracking resumes.
|
||||
|
||||
Features include:
|
||||
|
||||
- history_lines(int) can define a maximum size for the terminal screen history
|
||||
- stay_at_bottom(bool) can be used to cause the terminal to keep scrolled to the bottom
|
||||
- ansi(bool) enables ANSI sequences within the text to control text colors
|
||||
- style_table() can be used to define custom color/font/weight/size combinations
|
||||
|
||||
What this widget is NOT is a full terminal emulator; it does NOT
|
||||
handle stdio redirection, pipes, pseudo ttys, termio character cooking,
|
||||
keyboard input processing, screen addressing, random cursor positioning,
|
||||
curses(3) compatibility, or VT100/xterm emulation.
|
||||
|
||||
It is a simple text display widget that leverages the features of the
|
||||
Fl_Text_Display base class to handle terminal-like behavior, such as
|
||||
logging events or debug information.
|
||||
|
||||
Example use:
|
||||
\code
|
||||
|
||||
#include <FL/Fl_Simple_Terminal.H>
|
||||
:
|
||||
tty = new Fl_Simple_Terminal(...);
|
||||
tty->ansi(true); // enable use of "\033[#m"
|
||||
:
|
||||
tty->printf("The time is now: \033[32m%s\033[0m", date_time_str);
|
||||
|
||||
\endcode
|
||||
|
||||
Example application:
|
||||
\dontinclude simple-terminal.cxx
|
||||
\skip //START
|
||||
\until //END
|
||||
|
||||
Style Tables For Color/Font/Fontsize Control
|
||||
--------------------------------------------
|
||||
Internally this widget derives from Fl_Text_Display, and therefore
|
||||
inherits some of its idiosyncracies. In particular, when colors
|
||||
are used, the base class's concept of a 'style table' is used.
|
||||
|
||||
The 'style table' is similar to a color mapped image; where each
|
||||
pixel is a single value that is an index into a table of colors
|
||||
to minimize per-pixel memory use.
|
||||
|
||||
The style table has a similar goal; since every character in the
|
||||
terminal can potentially be a different color, instead of managing
|
||||
several integer attribute values per-character, a single character
|
||||
for each character is used as an index into the style table, choosing
|
||||
one of the available color/font/weight/size values available.
|
||||
This saves on as much as 3 to 4 times the memory use, useful when
|
||||
there's a large amount of text.
|
||||
|
||||
When ansi() is set to 'true', ANSI sequences of the form "\033[#m"
|
||||
can be used to select different colors, font faces, font weights (bold,italic..),
|
||||
and font sizes, where '#' is the index number into the style table. Example:
|
||||
|
||||
\code
|
||||
"\033[0mThis text uses the 1st entry in the style table\n"
|
||||
"\033[1mThis text uses the 2nd entry in the style table\n"
|
||||
"\033[2mThis text uses the 3rd entry in the style table\n"
|
||||
etc..
|
||||
\endcode
|
||||
|
||||
There is a built-in style table that provides some
|
||||
commonly used ANSI colors for "\033[30m" through "\033[37m"
|
||||
(blk,red,grn,yel,blu,mag,cyn,wht), and a brighter version of those
|
||||
colors for "\033[40" through "\033[47m". See ansi(bool) for more info.
|
||||
|
||||
You can also supply a custom style table using
|
||||
style_table(Style_Table_Entry*,int,int), allowing you to define
|
||||
your own color/font/weight/size combinations. See that method's docs
|
||||
for more info.
|
||||
|
||||
All style index numbers are rounded to the size of the style table
|
||||
(via modulus) to protect the style array from overruns.
|
||||
|
||||
*/
|
||||
class FL_EXPORT Fl_Simple_Terminal : public Fl_Text_Display {
|
||||
protected:
|
||||
Fl_Text_Buffer *buf; // text buffer
|
||||
Fl_Text_Buffer *sbuf; // style buffer
|
||||
|
||||
private:
|
||||
int history_lines_; // max lines allowed in screen history
|
||||
bool stay_at_bottom_; // lets scroller chase last line in buffer
|
||||
bool ansi_; // enables ANSI sequences
|
||||
// scroll management
|
||||
int lines; // #lines in buffer (optimization: Fl_Text_Buffer slow to calc this)
|
||||
bool scrollaway; // true when user changed vscroll away from bottom
|
||||
bool scrolling; // true while scroll callback active
|
||||
// Fl_Text_Display vscrollbar's callback+data
|
||||
Fl_Callback *orig_vscroll_cb;
|
||||
void *orig_vscroll_data;
|
||||
// Style table
|
||||
const Fl_Text_Display::Style_Table_Entry *stable_; // the active style table
|
||||
int stable_size_; // active style table size (in bytes)
|
||||
int normal_style_index_; // "normal" style used by "\033[0m" reset sequence
|
||||
int current_style_index_; // current style used for drawing text
|
||||
|
||||
public:
|
||||
Fl_Simple_Terminal(int X,int Y,int W,int H,const char *l=0);
|
||||
~Fl_Simple_Terminal();
|
||||
|
||||
// Terminal options
|
||||
void stay_at_bottom(bool);
|
||||
bool stay_at_bottom() const;
|
||||
void history_lines(int);
|
||||
int history_lines() const;
|
||||
void ansi(bool val);
|
||||
bool ansi() const;
|
||||
void style_table(Fl_Text_Display::Style_Table_Entry *stable, int stable_size, int normal_style_index=0);
|
||||
const Fl_Text_Display::Style_Table_Entry *style_table() const;
|
||||
int style_table_size() const;
|
||||
void normal_style_index(int);
|
||||
int normal_style_index() const;
|
||||
void current_style_index(int);
|
||||
int current_style_index() const;
|
||||
|
||||
// Terminal text management
|
||||
void append(const char *s, int len=-1);
|
||||
void text(const char *s, int len=-1);
|
||||
const char* text() const;
|
||||
void printf(const char *fmt, ...);
|
||||
void vprintf(const char *fmt, va_list ap);
|
||||
void clear();
|
||||
void remove_lines(int start, int count);
|
||||
|
||||
private:
|
||||
// Methods blocking public access to the subclass
|
||||
// These are subclass methods that would give unexpected
|
||||
// results if used. By making them private, we effectively
|
||||
// "block" them.
|
||||
//
|
||||
// TODO: There are probably other Fl_Text_Display methods that
|
||||
// need to be blocked.
|
||||
//
|
||||
void insert(const char*) { }
|
||||
|
||||
public:
|
||||
// Fltk
|
||||
virtual void draw();
|
||||
|
||||
protected:
|
||||
// Internal methods
|
||||
void enforce_stay_at_bottom();
|
||||
void enforce_history_lines();
|
||||
void vscroll_cb2(Fl_Widget*, void*);
|
||||
static void vscroll_cb(Fl_Widget*, void*);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// End of "$Id$".
|
||||
//
|
||||
@@ -652,7 +652,7 @@ EXCLUDE_SYMBOLS += Fl_Native_File_Chooser_FLTK_Driver
|
||||
# directories that contain example code fragments that are included (see
|
||||
# the \include command).
|
||||
|
||||
EXAMPLE_PATH = ../test
|
||||
EXAMPLE_PATH = ../test ../examples
|
||||
|
||||
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
|
||||
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
|
||||
BIN
documentation/src/simple-terminal-default-ansi.png
Normal file
BIN
documentation/src/simple-terminal-default-ansi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
@@ -26,6 +26,7 @@ ALL = clipboard$(EXEEXT) \
|
||||
table-spreadsheet-with-keyboard-nav$(EXEEXT) \
|
||||
table-with-keynav$(EXEEXT) \
|
||||
tabs-simple$(EXEEXT) \
|
||||
simple-terminal$(EXEEXT) \
|
||||
textdisplay-with-colors$(EXEEXT) \
|
||||
texteditor-simple$(EXEEXT) \
|
||||
tree-simple$(EXEEXT) \
|
||||
|
||||
60
examples/simple-terminal.cxx
Normal file
60
examples/simple-terminal.cxx
Normal file
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// "$Id$"
|
||||
//
|
||||
// Simple Example app using Fl_Simple_Terminal. - erco 10/12/2017
|
||||
//
|
||||
// Copyright 2017 Greg Ercolano.
|
||||
// Copyright 1998-2016 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
#include <time.h> //START
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl_Simple_Terminal.H>
|
||||
|
||||
#define TERMINAL_HEIGHT 120
|
||||
|
||||
// Globals
|
||||
Fl_Double_Window *G_win = 0;
|
||||
Fl_Box *G_box = 0;
|
||||
Fl_Simple_Terminal *G_tty = 0;
|
||||
|
||||
// Append a date/time message to the terminal every 2 seconds
|
||||
void tick_cb(void *data) {
|
||||
time_t lt = time(NULL);
|
||||
G_tty->printf("Timer tick: \033[32m%s\033[0m\n", ctime(<));
|
||||
Fl::repeat_timeout(2.0, tick_cb, data);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
G_win = new Fl_Double_Window(500, 200+TERMINAL_HEIGHT, "Your App");
|
||||
G_win->begin();
|
||||
|
||||
G_box = new Fl_Box(0, 0, G_win->w(), 200,
|
||||
"Your app GUI in this area.\n\n"
|
||||
"Your app's debugging output in tty below");
|
||||
|
||||
// Add simple terminal to bottom of app window for scrolling history of status messages.
|
||||
G_tty = new Fl_Simple_Terminal(0,200,G_win->w(),TERMINAL_HEIGHT);
|
||||
G_tty->ansi(true); // enable use of "\033[32m"
|
||||
|
||||
G_win->end();
|
||||
G_win->resizable(G_win);
|
||||
G_win->show();
|
||||
Fl::add_timeout(0.5, tick_cb);
|
||||
return Fl::run();
|
||||
} //END
|
||||
|
||||
//
|
||||
// End of "$Id$".
|
||||
//
|
||||
@@ -59,6 +59,7 @@ set (CPPFILES
|
||||
Fl_Scroll.cxx
|
||||
Fl_Scrollbar.cxx
|
||||
Fl_Shared_Image.cxx
|
||||
Fl_Simple_Terminal.cxx
|
||||
Fl_Single_Window.cxx
|
||||
Fl_Slider.cxx
|
||||
Fl_Spinner.cxx
|
||||
|
||||
747
src/Fl_Simple_Terminal.cxx
Normal file
747
src/Fl_Simple_Terminal.cxx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -78,6 +78,7 @@ CPPFILES = \
|
||||
Fl_Scroll.cxx \
|
||||
Fl_Scrollbar.cxx \
|
||||
Fl_Shared_Image.cxx \
|
||||
Fl_Simple_Terminal.cxx \
|
||||
Fl_Single_Window.cxx \
|
||||
Fl_Slider.cxx \
|
||||
Fl_Spinner.cxx \
|
||||
|
||||
@@ -286,7 +286,7 @@ unittests$(EXEEXT): unittests.o
|
||||
|
||||
unittests.o: unittests.cxx unittest_about.cxx unittest_points.cxx unittest_lines.cxx unittest_circles.cxx \
|
||||
unittest_rects.cxx unittest_text.cxx unittest_symbol.cxx unittest_viewport.cxx unittest_images.cxx \
|
||||
unittest_schemes.cxx
|
||||
unittest_schemes.cxx unittest_simple_terminal.cxx
|
||||
|
||||
adjuster$(EXEEXT): adjuster.o
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ That was a blank line above this.
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Int_Input.H>
|
||||
#include <FL/Fl_Choice.H>
|
||||
#include <FL/Fl_Simple_Terminal.H>
|
||||
#include <FL/fl_ask.H>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -74,6 +75,7 @@ Fl_Button *top,
|
||||
Fl_Choice *btype;
|
||||
Fl_Choice *wtype;
|
||||
Fl_Int_Input *field;
|
||||
Fl_Simple_Terminal *tty = 0;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
@@ -95,7 +97,7 @@ WhenItem when_items[] = {
|
||||
};
|
||||
|
||||
void b_cb(Fl_Widget* o, void*) {
|
||||
printf("callback, selection = %d, event_clicks = %d\n",
|
||||
tty->printf("callback, selection = \033[31m%d\033[0m, event_clicks = \033[32m%d\033[0m\n",
|
||||
((Fl_Browser*)o)->value(), Fl::event_clicks());
|
||||
}
|
||||
|
||||
@@ -154,7 +156,7 @@ int main(int argc, char **argv) {
|
||||
int i;
|
||||
if (!Fl::args(argc,argv,i)) Fl::fatal(Fl::help);
|
||||
const char* fname = (i < argc) ? argv[i] : "browser.cxx";
|
||||
Fl_Double_Window window(720,400,fname);
|
||||
Fl_Double_Window window(720,520,fname);
|
||||
browser = new Fl_Select_Browser(0,0,window.w(),350,0);
|
||||
browser->type(FL_MULTI_BROWSER);
|
||||
//browser->type(FL_HOLD_BROWSER);
|
||||
@@ -232,6 +234,11 @@ int main(int argc, char **argv) {
|
||||
wtype->callback(wtype_cb);
|
||||
wtype->value(4); // FL_WHEN_RELEASE_ALWAYS is Fl_Browser's default
|
||||
|
||||
// Small terminal window for callback messages
|
||||
tty = new Fl_Simple_Terminal(0,400,720,120);
|
||||
tty->history_lines(50);
|
||||
tty->ansi(true);
|
||||
|
||||
window.resizable(browser);
|
||||
window.show(argc,argv);
|
||||
return Fl::run();
|
||||
|
||||
@@ -41,8 +41,12 @@
|
||||
#include <FL/Fl_PNM_Image.H>
|
||||
#include <FL/Fl_Light_Button.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Simple_Terminal.H>
|
||||
#include <string.h>
|
||||
|
||||
#define TERMINAL_HEIGHT 120
|
||||
#define TERMINAL_GREEN "\033[32m"
|
||||
#define TERMINAL_NORMAL "\033[0m"
|
||||
|
||||
//
|
||||
// Globals...
|
||||
@@ -52,6 +56,7 @@ Fl_Input *filter;
|
||||
Fl_File_Browser *files;
|
||||
Fl_File_Chooser *fc;
|
||||
Fl_Shared_Image *image = 0;
|
||||
Fl_Simple_Terminal *tty = 0;
|
||||
|
||||
// for choosing extra groups
|
||||
Fl_Choice *ch_extra;
|
||||
@@ -101,7 +106,10 @@ main(int argc, // I - Number of command-line arguments
|
||||
Fl_Shared_Image::add_handler(ps_check);
|
||||
|
||||
// Make the main window...
|
||||
window = new Fl_Double_Window(400, 215, "File Chooser Test");
|
||||
window = new Fl_Double_Window(400, 215+TERMINAL_HEIGHT, "File Chooser Test");
|
||||
|
||||
tty = new Fl_Simple_Terminal(0,215,window->w(),TERMINAL_HEIGHT);
|
||||
tty->ansi(true);
|
||||
|
||||
filter = new Fl_Input(50, 10, 315, 25, "Filter:");
|
||||
// Process standard arguments and find filter argument if present
|
||||
@@ -221,11 +229,11 @@ fc_callback(Fl_File_Chooser *fc, // I - File chooser
|
||||
const char *filename; // Current filename
|
||||
|
||||
|
||||
printf("fc_callback(fc = %p, data = %p)\n", fc, data);
|
||||
tty->printf("fc_callback(fc = %p, data = %p)\n", fc, data);
|
||||
|
||||
filename = fc->value();
|
||||
|
||||
printf(" filename = \"%s\"\n", filename ? filename : "(null)");
|
||||
tty->printf(" filename = \"%s\"\n", filename ? filename : "(null)");
|
||||
}
|
||||
|
||||
|
||||
@@ -365,6 +373,8 @@ show_callback(void)
|
||||
if (!fc->value(i))
|
||||
break;
|
||||
|
||||
tty->printf("%d/%d) %sPicked: '%s'%s\n", i, count, TERMINAL_GREEN, fc->value(i), TERMINAL_NORMAL);
|
||||
|
||||
fl_filename_relative(relative, sizeof(relative), fc->value(i));
|
||||
|
||||
files->add(relative,
|
||||
|
||||
@@ -28,9 +28,15 @@
|
||||
#include <FL/Fl_Toggle_Button.H>
|
||||
#include <FL/Fl_Light_Button.H>
|
||||
#include <FL/Fl_Color_Chooser.H>
|
||||
#include <FL/Fl_Simple_Terminal.H>
|
||||
|
||||
#define TERMINAL_HEIGHT 120
|
||||
|
||||
// Globals
|
||||
Fl_Simple_Terminal *G_tty = 0;
|
||||
|
||||
void cb(Fl_Widget *ob) {
|
||||
printf("Callback for %s '%s'\n",ob->label(),((Fl_Input*)ob)->value());
|
||||
G_tty->printf("Callback for %s '%s'\n",ob->label(),((Fl_Input*)ob)->value());
|
||||
}
|
||||
|
||||
int when = 0;
|
||||
@@ -43,11 +49,11 @@ void toggle_cb(Fl_Widget *o, long v) {
|
||||
|
||||
void test(Fl_Input *i) {
|
||||
if (i->changed()) {
|
||||
i->clear_changed(); printf("%s '%s'\n",i->label(),i->value());
|
||||
i->clear_changed(); G_tty->printf("%s '%s'\n",i->label(),i->value());
|
||||
char utf8buf[10];
|
||||
int last = fl_utf8encode(i->index(i->position()), utf8buf);
|
||||
utf8buf[last] = 0;
|
||||
printf("Symbol at cursor position: %s\n", utf8buf);
|
||||
G_tty->printf("Symbol at cursor position: %s\n", utf8buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +92,8 @@ int main(int argc, char **argv) {
|
||||
// calling fl_contrast below will return good results
|
||||
Fl::args(argc, argv);
|
||||
Fl::get_system_colors();
|
||||
Fl_Window *window = new Fl_Window(400,420);
|
||||
Fl_Window *window = new Fl_Window(400,420+TERMINAL_HEIGHT);
|
||||
G_tty = new Fl_Simple_Terminal(0,420,window->w(),TERMINAL_HEIGHT);
|
||||
|
||||
int y = 10;
|
||||
input[0] = new Fl_Input(70,y,300,30,"Normal:"); y += 35;
|
||||
@@ -153,6 +160,7 @@ int main(int argc, char **argv) {
|
||||
b->tooltip("Color of the text");
|
||||
|
||||
window->end();
|
||||
window->resizable(G_tty);
|
||||
window->show(argc,argv);
|
||||
return Fl::run();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,12 @@
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Input_Choice.H>
|
||||
#include <FL/Fl_Simple_Terminal.H>
|
||||
|
||||
#define TERMINAL_HEIGHT 120
|
||||
|
||||
// Globals
|
||||
Fl_Simple_Terminal *G_tty = 0;
|
||||
|
||||
void buttcb(Fl_Widget*,void*data) {
|
||||
Fl_Input_Choice *in=(Fl_Input_Choice *)data;
|
||||
@@ -28,18 +34,19 @@ void buttcb(Fl_Widget*,void*data) {
|
||||
if ( flag ) in->activate();
|
||||
else in->deactivate();
|
||||
if (in->changed()) {
|
||||
printf("Callback: changed() is set\n");
|
||||
G_tty->printf("Callback: changed() is set\n");
|
||||
in->clear_changed();
|
||||
}
|
||||
}
|
||||
|
||||
void input_choice_cb(Fl_Widget*,void*data) {
|
||||
Fl_Input_Choice *in=(Fl_Input_Choice *)data;
|
||||
fprintf(stderr, "Value='%s'\n", (const char*)in->value());
|
||||
G_tty->printf("Value='%s'\n", (const char*)in->value());
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Fl_Double_Window win(300, 200);
|
||||
Fl_Double_Window win(300, 200+TERMINAL_HEIGHT);
|
||||
G_tty = new Fl_Simple_Terminal(0,200,win.w(),TERMINAL_HEIGHT);
|
||||
|
||||
Fl_Input_Choice in(40,40,100,28,"Test");
|
||||
in.callback(input_choice_cb, (void*)&in);
|
||||
|
||||
@@ -30,9 +30,15 @@
|
||||
#include <stdlib.h>
|
||||
#include "../src/flstring.h"
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/Fl_Simple_Terminal.H>
|
||||
|
||||
#define TERMINAL_HEIGHT 120
|
||||
|
||||
// Globals
|
||||
Fl_Simple_Terminal *G_tty = 0;
|
||||
|
||||
void window_cb(Fl_Widget* w, void*) {
|
||||
puts("window callback called");
|
||||
puts("window callback called"); // end of program, so stdout instead of G_tty
|
||||
((Fl_Double_Window *)w)->hide();
|
||||
}
|
||||
|
||||
@@ -40,11 +46,11 @@ void test_cb(Fl_Widget* w, void*) {
|
||||
Fl_Menu_* mw = (Fl_Menu_*)w;
|
||||
const Fl_Menu_Item* m = mw->mvalue();
|
||||
if (!m)
|
||||
printf("NULL\n");
|
||||
G_tty->printf("NULL\n");
|
||||
else if (m->shortcut())
|
||||
printf("%s - %s\n", m->label(), fl_shortcut_label(m->shortcut()));
|
||||
G_tty->printf("%s - %s\n", m->label(), fl_shortcut_label(m->shortcut()));
|
||||
else
|
||||
printf("%s\n", m->label());
|
||||
G_tty->printf("%s\n", m->label());
|
||||
}
|
||||
|
||||
void quit_cb(Fl_Widget*, void*) {exit(0);}
|
||||
@@ -211,7 +217,9 @@ int main(int argc, char **argv) {
|
||||
sprintf(buf,"item %d",i);
|
||||
hugemenu[i].text = strdup(buf);
|
||||
}
|
||||
Fl_Double_Window window(WIDTH,400);
|
||||
Fl_Double_Window window(WIDTH,400+TERMINAL_HEIGHT);
|
||||
G_tty = new Fl_Simple_Terminal(0,400,WIDTH,TERMINAL_HEIGHT);
|
||||
|
||||
window.callback(window_cb);
|
||||
Fl_Menu_Bar menubar(0,0,WIDTH,30); menubar.menu(menutable);
|
||||
menubar.callback(test_cb);
|
||||
|
||||
@@ -27,10 +27,14 @@
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl_Native_File_Chooser.H>
|
||||
#include <FL/Fl_Help_View.H>
|
||||
#include <FL/Fl_Simple_Terminal.H>
|
||||
|
||||
#define TERMINAL_HEIGHT 120
|
||||
|
||||
// GLOBALS
|
||||
Fl_Input *G_filename = NULL;
|
||||
Fl_Multiline_Input *G_filter = NULL;
|
||||
Fl_Simple_Terminal *G_tty = NULL;
|
||||
|
||||
void PickFile_CB(Fl_Widget*, void*) {
|
||||
// Create native chooser
|
||||
@@ -41,13 +45,15 @@ void PickFile_CB(Fl_Widget*, void*) {
|
||||
native.preset_file(G_filename->value());
|
||||
// Show native chooser
|
||||
switch ( native.show() ) {
|
||||
case -1: fprintf(stderr, "ERROR: %s\n", native.errmsg()); break; // ERROR
|
||||
case 1: fprintf(stderr, "*** CANCEL\n"); fl_beep(); break; // CANCEL
|
||||
case -1: G_tty->printf("ERROR: %s\n", native.errmsg()); break; // ERROR
|
||||
case 1: G_tty->printf("*** CANCEL\n"); fl_beep(); break; // CANCEL
|
||||
default: // PICKED FILE
|
||||
if ( native.filename() ) {
|
||||
G_filename->value(native.filename());
|
||||
G_tty->printf("filename='%s'\n", native.filename());
|
||||
} else {
|
||||
G_filename->value("NULL");
|
||||
G_tty->printf("filename='(null)'\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -61,13 +67,15 @@ void PickDir_CB(Fl_Widget*, void*) {
|
||||
native.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY);
|
||||
// Show native chooser
|
||||
switch ( native.show() ) {
|
||||
case -1: fprintf(stderr, "ERROR: %s\n", native.errmsg()); break; // ERROR
|
||||
case 1: fprintf(stderr, "*** CANCEL\n"); fl_beep(); break; // CANCEL
|
||||
case -1: G_tty->printf("ERROR: %s\n", native.errmsg()); break; // ERROR
|
||||
case 1: G_tty->printf("*** CANCEL\n"); fl_beep(); break; // CANCEL
|
||||
default: // PICKED DIR
|
||||
if ( native.filename() ) {
|
||||
G_filename->value(native.filename());
|
||||
G_tty->printf("dirname='%s'\n", native.filename());
|
||||
} else {
|
||||
G_filename->value("NULL");
|
||||
G_tty->printf("dirname='(null)'\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -91,10 +99,12 @@ int main(int argc, char **argv) {
|
||||
argn++;
|
||||
#endif
|
||||
|
||||
Fl_Window *win = new Fl_Window(640, 400, "Native File Chooser Test");
|
||||
Fl_Window *win = new Fl_Window(640, 400+TERMINAL_HEIGHT, "Native File Chooser Test");
|
||||
win->size_range(win->w(), win->h(), 0, 0);
|
||||
win->begin();
|
||||
{
|
||||
G_tty = new Fl_Simple_Terminal(0,400,win->w(),TERMINAL_HEIGHT);
|
||||
|
||||
int x = 80, y = 10;
|
||||
G_filename = new Fl_Input(x, y, win->w()-80-10, 25, "Filename");
|
||||
G_filename->value(argc <= argn ? "." : argv[argn]);
|
||||
@@ -131,10 +141,10 @@ int main(int argc, char **argv) {
|
||||
" Apps<font color=#55f><Ctrl-I></font>*.app\n"
|
||||
"</pre>\n");
|
||||
|
||||
Fl_Button *but = new Fl_Button(win->w()-x-10, win->h()-25-10, 80, 25, "Pick File");
|
||||
Fl_Button *but = new Fl_Button(win->w()-x-10, win->h()-TERMINAL_HEIGHT-25-10, 80, 25, "Pick File");
|
||||
but->callback(PickFile_CB);
|
||||
|
||||
Fl_Button *butdir = new Fl_Button(but->x()-x-10, win->h()-25-10, 80, 25, "Pick Dir");
|
||||
Fl_Button *butdir = new Fl_Button(but->x()-x-10, win->h()-TERMINAL_HEIGHT-25-10, 80, 25, "Pick Dir");
|
||||
butdir->callback(PickDir_CB);
|
||||
|
||||
win->resizable(G_filter);
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/fl_ask.H>
|
||||
#include <FL/Fl_Table_Row.H>
|
||||
#include <FL/Fl_Simple_Terminal.H>
|
||||
|
||||
#define TERMINAL_HEIGHT 120
|
||||
|
||||
// Globals
|
||||
Fl_Simple_Terminal *G_tty = 0;
|
||||
|
||||
// Simple demonstration class to derive from Fl_Table_Row
|
||||
class DemoTable : public Fl_Table_Row
|
||||
@@ -99,7 +105,7 @@ void DemoTable::draw_cell(TableContext context,
|
||||
}
|
||||
|
||||
case CONTEXT_TABLE:
|
||||
fprintf(stderr, "TABLE CONTEXT CALLED\n");
|
||||
G_tty->printf("TABLE CONTEXT CALLED\n");
|
||||
return;
|
||||
|
||||
case CONTEXT_ENDPAGE:
|
||||
@@ -121,9 +127,9 @@ void DemoTable::event_callback2()
|
||||
int R = callback_row(),
|
||||
C = callback_col();
|
||||
TableContext context = callback_context();
|
||||
printf("'%s' callback: ", (label() ? label() : "?"));
|
||||
printf("Row=%d Col=%d Context=%d Event=%d InteractiveResize? %d\n",
|
||||
R, C, (int)context, (int)Fl::event(), (int)is_interactive_resize());
|
||||
const char *name = label() ? label() : "?";
|
||||
G_tty->printf("'%s' callback: Row=%d Col=%d Context=%d Event=%d InteractiveResize? %d\n",
|
||||
name, R, C, (int)context, (int)Fl::event(), (int)is_interactive_resize());
|
||||
}
|
||||
|
||||
// GLOBAL TABLE WIDGET
|
||||
@@ -339,7 +345,9 @@ Fl_Menu_Item type_choices[] = {
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Fl_Window win(900, 730);
|
||||
Fl_Window win(900, 730+TERMINAL_HEIGHT);
|
||||
|
||||
G_tty = new Fl_Simple_Terminal(0,730,win.w(),TERMINAL_HEIGHT);
|
||||
|
||||
G_table = new DemoTable(20, 20, 860, 460, "Demo");
|
||||
G_table->selection_color(FL_YELLOW);
|
||||
|
||||
43
test/tree.fl
43
test/tree.fl
@@ -38,6 +38,9 @@ decl {\#include <FL/Fl_Color_Chooser.H>} {public global
|
||||
decl {\#include <FL/Fl_Text_Display.H>} {public global
|
||||
}
|
||||
|
||||
decl {\#include <FL/Fl_Simple_Terminal.H>} {public global
|
||||
}
|
||||
|
||||
decl {int G_cb_counter = 0;} {
|
||||
comment {// Global callback event counter} private local
|
||||
}
|
||||
@@ -74,7 +77,7 @@ height += 10;
|
||||
if ( height > 50 ) height = 20;
|
||||
cw->resize(cw->x(), cw->y(), cw->w(), height);
|
||||
tree->redraw(); // adjusted height
|
||||
fprintf(stderr, "'%s' button pushed (height=%d)\\n", w->label(), height);} {}
|
||||
tty->printf("'%s' button pushed (height=%d)\\n", w->label(), height);} {}
|
||||
}
|
||||
|
||||
Function {AssignUserIcons()} {
|
||||
@@ -144,8 +147,7 @@ for ( Fl_Tree_Item *item = tree->first(); item; item=item->next()) {
|
||||
item->userdeicon(0);
|
||||
}
|
||||
}
|
||||
tree->redraw();} {selected
|
||||
}
|
||||
tree->redraw();} {}
|
||||
}
|
||||
|
||||
Function {RebuildTree()} {
|
||||
@@ -360,7 +362,7 @@ Function {} {open
|
||||
} {
|
||||
Fl_Window window {
|
||||
label tree open
|
||||
xywh {600 253 1045 580} type Double hide
|
||||
xywh {539 25 1045 730} type Double visible
|
||||
} {
|
||||
Fl_Group tree {
|
||||
label Tree
|
||||
@@ -368,7 +370,7 @@ Function {} {open
|
||||
callback {G_cb_counter++; // Increment callback counter whenever tree callback is invoked
|
||||
Fl_Tree_Item *item = tree->callback_item();
|
||||
if ( item ) {
|
||||
fprintf(stderr, "TREE CALLBACK: label='%s' userdata=%ld reason=%s, changed=%d",
|
||||
tty->printf("TREE CALLBACK: label='%s' userdata=%ld reason=%s, changed=%d",
|
||||
item->label(),
|
||||
(long)(fl_intptr_t)tree->user_data(),
|
||||
reason_as_name(tree->callback_reason()),
|
||||
@@ -377,12 +379,12 @@ if ( item ) {
|
||||
// Should only happen if reason==FL_TREE_REASON_RESELECTED.
|
||||
//
|
||||
if ( Fl::event_clicks() > 0 ) {
|
||||
fprintf(stderr, ", clicks=%d\\n", (Fl::event_clicks()+1));
|
||||
tty->printf(", clicks=%d\\n", (Fl::event_clicks()+1));
|
||||
} else {
|
||||
fprintf(stderr, "\\n");
|
||||
tty->printf("\\n");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "TREE CALLBACK: reason=%s, changed=%d, item=(no item -- probably multiple items were changed at once)\\n",
|
||||
tty->printf("TREE CALLBACK: reason=%s, changed=%d, item=(no item -- probably multiple items were changed at once)\\n",
|
||||
reason_as_name(tree->callback_reason()),
|
||||
tree->changed() ? 1 : 0);
|
||||
}
|
||||
@@ -896,7 +898,7 @@ Clears all items} xywh {570 471 95 16} labelsize 9
|
||||
Fl_Button testcallbackflag_button {
|
||||
label {Test Callback Flag}
|
||||
callback {Fl_Tree_Item *root = tree->root();
|
||||
fprintf(stderr, "--- Checking docallback off\\n");
|
||||
tty->printf("--- Checking docallback off\\n");
|
||||
if (!root) return;
|
||||
|
||||
//// "OFF" TEST
|
||||
@@ -961,7 +963,7 @@ fl_alert("TEST COMPLETED\\n If you didn't see any error dialogs, test PASSED.");
|
||||
Fl_Button testrootshowself_button {
|
||||
label {Root Show Self}
|
||||
callback {Fl_Tree_Item *root = tree->root();
|
||||
fprintf(stderr, "--- Show Tree\\n");
|
||||
tty->printf("--- Show Tree\\n");
|
||||
if (root) root->show_self();}
|
||||
tooltip {Test the root->'show_self() method to show the entire tree on stdout} xywh {570 511 95 16} labelsize 9
|
||||
}
|
||||
@@ -1231,11 +1233,11 @@ If nothing selected, all are changed} xywh {758 174 100 16} selection_color 1 la
|
||||
}
|
||||
Fl_Button showselected_button {
|
||||
label {Show Selected}
|
||||
callback {fprintf(stderr, "--- SELECTED ITEMS\\n");
|
||||
callback {tty->printf("--- SELECTED ITEMS\\n");
|
||||
for ( Fl_Tree_Item *item = tree->first_selected_item();
|
||||
item;
|
||||
item = tree->next_selected_item(item) ) {
|
||||
fprintf(stderr, "\\t%s\\n", item->label() ? item->label() : "???");
|
||||
tty->printf("\\t%s\\n", item->label() ? item->label() : "???");
|
||||
}}
|
||||
tooltip {Clears the selected items} xywh {864 134 95 16} labelsize 9
|
||||
}
|
||||
@@ -1298,15 +1300,15 @@ tree->redraw();}
|
||||
}
|
||||
Fl_Button nextselected_button {
|
||||
label {next_selected()}
|
||||
callback {printf("--- TEST next_selected():\\n");
|
||||
printf(" // Walk down the tree (forwards)\\n");
|
||||
callback {tty->printf("--- TEST next_selected():\\n");
|
||||
tty->printf(" // Walk down the tree (forwards)\\n");
|
||||
for ( Fl_Tree_Item *i=tree->first_selected_item(); i; i=tree->next_selected_item(i, FL_Down) ) {
|
||||
printf(" Selected item: %s\\n", i->label()?i->label():"<nolabel>");
|
||||
tty->printf(" Selected item: %s\\n", i->label()?i->label():"<nolabel>");
|
||||
}
|
||||
|
||||
printf(" // Walk up the tree (backwards)\\n");
|
||||
tty->printf(" // Walk up the tree (backwards)\\n");
|
||||
for ( Fl_Tree_Item *i=tree->last_selected_item(); i; i=tree->next_selected_item(i, FL_Up) ) {
|
||||
printf(" Selected item: %s\\n", i->label()?i->label():"<nolabel>");
|
||||
tty->printf(" Selected item: %s\\n", i->label()?i->label():"<nolabel>");
|
||||
}}
|
||||
tooltip {Tests the Fl_Tree::next_selected() function} xywh {713 239 95 16} labelsize 9
|
||||
}
|
||||
@@ -1703,7 +1705,7 @@ if ( !helpwin ) {
|
||||
}
|
||||
helpwin->resizable(helpdisp);
|
||||
helpwin->show();}
|
||||
tooltip {Suggestions on how to do tests} xywh {935 554 95 16} labelsize 9
|
||||
tooltip {Suggestions on how to do tests} xywh {935 545 95 16} labelsize 9
|
||||
}
|
||||
Fl_Value_Slider tree_scrollbar_size_slider {
|
||||
label {Fl_Tree::scrollbar_size()}
|
||||
@@ -1730,6 +1732,11 @@ tree->redraw();}
|
||||
Fl_Box resizer_box {
|
||||
xywh {0 263 15 14}
|
||||
}
|
||||
Fl_Box tty {
|
||||
label label selected
|
||||
xywh {16 571 1014 149} box DOWN_BOX color 0
|
||||
class Fl_Simple_Terminal
|
||||
}
|
||||
}
|
||||
code {// Initialize Tree
|
||||
tree->root_label("ROOT");
|
||||
|
||||
124
test/unittest_simple_terminal.cxx
Normal file
124
test/unittest_simple_terminal.cxx
Normal file
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// "$Id$"
|
||||
//
|
||||
// Unit tests for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2017 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
#include <time.h>
|
||||
#include <FL/Fl_Group.H>
|
||||
#include <FL/Fl_Simple_Terminal.H>
|
||||
|
||||
//
|
||||
//------- test the Fl_Simple_Terminal drawing capabilities ----------
|
||||
//
|
||||
class SimpleTerminal : public Fl_Group {
|
||||
Fl_Simple_Terminal *tty1;
|
||||
Fl_Simple_Terminal *tty2;
|
||||
Fl_Simple_Terminal *tty3;
|
||||
void AnsiTestPattern(Fl_Simple_Terminal *tty) {
|
||||
tty->append("\033[30mBlack Courier 14\033[0m Normal text\n"
|
||||
"\033[31mRed Courier 14\033[0m Normal text\n"
|
||||
"\033[32mGreen Courier 14\033[0m Normal text\n"
|
||||
"\033[33mYellow Courier 14\033[0m Normal text\n"
|
||||
"\033[34mBlue Courier 14\033[0m Normal text\n"
|
||||
"\033[35mMagenta Courier 14\033[0m Normal text\n"
|
||||
"\033[36mCyan Courier 14\033[0m Normal text\n"
|
||||
"\033[37mWhite Courier 14\033[0m Normal text\n"
|
||||
"\033[40mBright Black Courier 14\033[0m Normal text\n"
|
||||
"\033[41mBright Red Courier 14\033[0m Normal text\n"
|
||||
"\033[42mBright Green Courier 14\033[0m Normal text\n"
|
||||
"\033[43mBright Yellow Courier 14\033[0m Normal text\n"
|
||||
"\033[44mBright Blue Courier 14\033[0m Normal text\n"
|
||||
"\033[45mBright Magenta Courier 14\033[0m Normal text\n"
|
||||
"\033[46mBright Cyan Courier 14\033[0m Normal text\n"
|
||||
"\033[47mBright White Courier 14\033[0m Normal text\n"
|
||||
"\n"
|
||||
"\033[31mRed\033[32mGreen\033[33mYellow\033[34mBlue\033[35mMagenta\033[36mCyan\033[37mWhite\033[0m - "
|
||||
"\033[31mX\033[32mX\033[33mX\033[34mX\033[35mX\033[36mX\033[37mX\033[0m\n"
|
||||
"\033[41mRed\033[42mGreen\033[43mYellow\033[44mBlue\033[45mMagenta\033[46mCyan\033[47mWhite\033[0m - "
|
||||
"\033[41mX\033[42mX\033[43mX\033[44mX\033[45mX\033[46mX\033[47mX\033[0m\n");
|
||||
}
|
||||
void GrayTestPattern(Fl_Simple_Terminal *tty) {
|
||||
tty->append("Grayscale Test Pattern\n"
|
||||
"--------------------------\n"
|
||||
"\033[0m 100% white Courier 14\n"
|
||||
"\033[1m 90% white Courier 14\n"
|
||||
"\033[2m 80% white Courier 14\n"
|
||||
"\033[3m 70% white Courier 14\n"
|
||||
"\033[4m 60% white Courier 14\n"
|
||||
"\033[5m 50% white Courier 14\n"
|
||||
"\033[6m 40% white Courier 14\n"
|
||||
"\033[7m 30% white Courier 14\n"
|
||||
"\033[8m 20% white Courier 14\n"
|
||||
"\033[9m 10% white Courier 14\n"
|
||||
"\033[0m");
|
||||
}
|
||||
static void DateTimer_CB(void *data) {
|
||||
Fl_Simple_Terminal *tty = (Fl_Simple_Terminal*)data;
|
||||
time_t lt = time(NULL);
|
||||
tty->printf("The time and date is now: %s", ctime(<));
|
||||
Fl::repeat_timeout(3.0, DateTimer_CB, data);
|
||||
}
|
||||
public:
|
||||
static Fl_Widget *create() {
|
||||
return new SimpleTerminal(TESTAREA_X, TESTAREA_Y, TESTAREA_W, TESTAREA_H);
|
||||
}
|
||||
SimpleTerminal(int x, int y, int w, int h) : Fl_Group(x, y, w, h) {
|
||||
static Fl_Text_Display::Style_Table_Entry my_stable[] = { // 10 entry grayscale
|
||||
// Font Color Font Face Font Size ANSI Sequence
|
||||
// ---------- ---------------- --------- -------------
|
||||
{ 0xffffff00, FL_COURIER_BOLD, 14 }, // "\033[0m" 0 white 100%
|
||||
{ 0xe6e6e600, FL_COURIER_BOLD, 14 }, // "\033[1m" 1 white 90%
|
||||
{ 0xcccccc00, FL_COURIER_BOLD, 14 }, // "\033[2m" 2 white 80%
|
||||
{ 0xb3b3b300, FL_COURIER_BOLD, 14 }, // "\033[3m" 3 white 70%
|
||||
{ 0x99999900, FL_COURIER_BOLD, 14 }, // "\033[4m" 4 white 60%
|
||||
{ 0x80808000, FL_COURIER_BOLD, 14 }, // "\033[5m" 5 white 50% "\033[0m"
|
||||
{ 0x66666600, FL_COURIER_BOLD, 14 }, // "\033[6m" 6 white 40%
|
||||
{ 0x4d4d4d00, FL_COURIER_BOLD, 14 }, // "\033[7m" 7 white 30%
|
||||
{ 0x33333300, FL_COURIER_BOLD, 14 }, // "\033[8m" 8 white 20%
|
||||
{ 0x1a1a1a00, FL_COURIER_BOLD, 14 }, // "\033[9m" 9 white 10%
|
||||
};
|
||||
int tty_h = (h/3.5);
|
||||
int tty_y1 = y+(tty_h*0)+20;
|
||||
int tty_y2 = y+(tty_h*1)+40;
|
||||
int tty_y3 = y+(tty_h*2)+60;
|
||||
|
||||
// TTY1
|
||||
tty1 = new Fl_Simple_Terminal(x, tty_y1, w, tty_h,"Tty 1: ANSI off");
|
||||
tty1->ansi(false);
|
||||
Fl::add_timeout(0.5, DateTimer_CB, (void*)tty1);
|
||||
|
||||
// TTY2
|
||||
tty2 = new Fl_Simple_Terminal(x, tty_y2, w, tty_h,"Tty 2: ANSI on");
|
||||
tty2->ansi(true);
|
||||
AnsiTestPattern(tty2);
|
||||
Fl::add_timeout(0.5, DateTimer_CB, (void*)tty2);
|
||||
|
||||
// TTY3
|
||||
tty3 = new Fl_Simple_Terminal(x, tty_y3, w, tty_h, "Tty 3: Grayscale Style Table");
|
||||
tty3->style_table(my_stable, sizeof(my_stable), 0);
|
||||
tty3->ansi(true);
|
||||
GrayTestPattern(tty3);
|
||||
Fl::add_timeout(0.5, DateTimer_CB, (void*)tty3);
|
||||
|
||||
end();
|
||||
}
|
||||
};
|
||||
|
||||
UnitTest simple_terminal("simple terminal", SimpleTerminal::create);
|
||||
|
||||
//
|
||||
// End of "$Id$"
|
||||
//
|
||||
@@ -153,6 +153,7 @@ public:
|
||||
#include "unittest_viewport.cxx"
|
||||
#include "unittest_scrollbarsize.cxx"
|
||||
#include "unittest_schemes.cxx"
|
||||
#include "unittest_simple_terminal.cxx"
|
||||
|
||||
// callback whenever the browser value changes
|
||||
void Browser_CB(Fl_Widget*, void*) {
|
||||
|
||||
Reference in New Issue
Block a user