Text Display
#!/usr/bin/env python
from fltk import *
import sys
import os
def quit():
win = Fl.first_window()
while win := Fl.first_window():
win.hide()
class MyWindow(Fl_Window):
def __init__(self,width,height,textsize=14,text="",margin=20):
super().__init__(width,height)
coords = (margin,margin,width-2*margin,height-2*margin)
self.mytext = Fl_Text_Display(*coords)
self.mytext.textsize(textsize)
self.bgcolor = fl_rgb_color(0,0,30)
self.fgcolor = fl_rgb_color(255,255,130)
self.mytext.textcolor(self.fgcolor)
self.mytext.color(self.bgcolor)
self.textbuffer = Fl_Text_Buffer()
self.textbuffer.text(text)
self.mytext.buffer(self.textbuffer)
self.add(self.mytext)
self.end()
def handle(self,x):
match x:
case 12:
return self.handlekey()
return super().handle(x)
def handlekey(self):
k = Fl.event_key()
t = Fl.event_text()
print("MyWindow","key",k,"text",t)
match t.lower():
case "q":
print("Window Quit")
quit()
return 1
return 0
def main():
args = sys.argv[1:]
switches = []
other = []
for x in args:
if x[0] == "-":
switches.append(x)
else:
other.append(x)
# we pass all switches to the Fl handler,
# but all other text we want to deal with.
argv = [sys.argv[0]] + switches
# configure using environment variables
# rather than having a more elaborate arg processor
geom = os.getenv("GEOMETRY","400,300")
margin = os.getenv("MARGIN","20")
textsize = os.getenv("TEXTSIZE","14")
# validate env variables for sanity
try:
width, height = [ int(x) for x in geom.split(",") ]
except ValueError:
print("Bad GEOMETRY",geom)
exit(1)
try:
textsize = int(textsize)
except ValueError:
print("Bad TEXTSIZE",textsize)
exit(1)
try:
margin = int(margin)
if margin < 0:
raise ValueError()
coords = (margin,margin,width-2*margin,height-2*margin)
if coords[2] <= 0 or coords[3] <= 0:
raise ValueError()
except ValueError:
print("Bad MARGIN",margin)
exit(1)
# the text that will be displayed:
# the result of concatenating command line args
# one per line and any text piped in.
if not sys.stdin.isatty():
other.append(sys.stdin.read())
text = "\n".join(other)
window = MyWindow(width,height,textsize=textsize,text=text,margin=margin)
window.show(argv)
Fl.run()
print("Finished")
if __name__ == "__main__":
main()
A similar C++ version is this. It also illustrates how to turn naked pointers
of old style C++ into std::unique_ptrs.
/*
build with
g++ -o fl_text_display fl_text_display.cpp -lfltk -lX11 -lm
*/
// for unique_ptr and make_unique
#include <memory>
// for cout and cin
#include <iostream>
// Needed for seeing if stdin is a pipe or a tty
#include <stdio.h>
#include <unistd.h>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Text_Display.H>
#include <FL/Fl_Text_Buffer.H>
class MyWindow : public Fl_Window {
protected:
std::unique_ptr<Fl_Text_Display> m_text_display;
std::unique_ptr<Fl_Text_Buffer> m_text_buffer;
int m_width;
int m_height;
int m_margin;
public:
virtual ~MyWindow() {
}
MyWindow(int width, int height, int margin) :
Fl_Window(width,height) {
m_width = width;
m_height = height;
m_margin = margin;
if(
(2 * m_margin) > m_width ||
(2 * m_margin) > m_height
) {
m_margin = 0;
}
m_text_display = std::make_unique<Fl_Text_Display>(m_margin,m_margin,m_width-2*m_margin,m_height-2*m_margin);
m_text_buffer = std::make_unique<Fl_Text_Buffer>();
m_text_display->buffer(*m_text_buffer);
m_text_display->textcolor(fl_rgb_color(255,255,130));
m_text_display->color(fl_rgb_color(0,0,30));
end();
}
void text(std::string txt) {
m_text_buffer->text(txt.c_str());
}
int handle(int x) {
switch(x) {
case 12:
return handlekey();
}
return 0;
}
int handlekey() {
switch(Fl::event_key()) {
case 'q':
case 'Q':
quit();
return 1;
}
return 0;
}
void quit() {
Fl_Window* win;
while( win = Fl::first_window() ) {
win->hide();
}
}
private:
};
std::string get_text() {
if( isatty(fileno(stdin)) ) return std::string();
std::istreambuf_iterator<char> begin(std::cin), end;
std::string buf(begin, end);
return buf;
}
int main(int argc, char **argv) {
std::string text = get_text();
std::unique_ptr<MyWindow> window = std::make_unique<MyWindow>(400,400,10);
window->text(text);
window->show(argc, argv);
return Fl::run();
}