#include "fltk/layout.h"
#include "fltk/util.h"
#include "fltk/Fl_Monitor_Arrangement.h"
+#include "fltk/Fl_Navigation.h"
#include <FL/Fl.H>
#include <FL/Fl_Tabs.H>
static std::set<OptionsDialog *> instances;
OptionsDialog::OptionsDialog()
- : Fl_Window(450, 460, _("VNC Viewer: Connection Options"))
+ : Fl_Window(580, 420, _("TigerVNC Options"))
{
int x, y;
+ Fl_Navigation *navigation;
Fl_Button *button;
- Fl_Tabs *tabs = new Fl_Tabs(OUTER_MARGIN, OUTER_MARGIN,
- w() - OUTER_MARGIN*2,
- h() - OUTER_MARGIN*2 - INNER_MARGIN - BUTTON_HEIGHT);
-
+ // Odd dimensions to get rid of extra borders
+ // FIXME: We need to retain the top border on Windows as they don't
+ // have any separator for the caption, which looks odd
+#ifdef WIN32
+ navigation = new Fl_Navigation(-1, 0, w()+2,
+ h() - INNER_MARGIN - BUTTON_HEIGHT - OUTER_MARGIN);
+#else
+ navigation = new Fl_Navigation(-1, -1, w()+2,
+ h()+1 - INNER_MARGIN - BUTTON_HEIGHT - OUTER_MARGIN);
+#endif
{
int tx, ty, tw, th;
- tabs->client_area(tx, ty, tw, th, TABS_HEIGHT);
+ navigation->client_area(tx, ty, tw, th, 150);
createCompressionPage(tx, ty, tw, th);
createSecurityPage(tx, ty, tw, th);
createMiscPage(tx, ty, tw, th);
}
- tabs->end();
+ navigation->end();
x = w() - BUTTON_WIDTH * 2 - INNER_MARGIN - OUTER_MARGIN;
y = h() - BUTTON_HEIGHT - OUTER_MARGIN;
void OptionsDialog::createMiscPage(int tx, int ty, int tw, int th)
{
- Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Misc."));
+ Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Miscellaneous"));
tx += OUTER_MARGIN;
ty += OUTER_MARGIN;
--- /dev/null
+/* Copyright 2022 Pierre Ossman for Cendio AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Scroll.H>
+
+#include "Fl_Navigation.h"
+
+Fl_Navigation::Fl_Navigation(int x, int y, int w, int h)
+ : Fl_Group(x, y, w, h)
+{
+ int dummy;
+
+ scroll = new Fl_Scroll(x, y, 1, 1);
+ scroll->type(Fl_Scroll::VERTICAL);
+ scroll->color(FL_BACKGROUND2_COLOR);
+
+ labels = new Fl_Group(x, y, 1, 1);
+ labels->end();
+
+ scroll->end();
+
+ pages = new Fl_Group(x, y, 1, 1);
+ pages->end();
+
+ Fl_Group::end();
+
+ // Just to resize things, and avoid code duplication
+ client_area(dummy, dummy, dummy, dummy, w/10);
+
+ begin();
+}
+
+Fl_Navigation::~Fl_Navigation()
+{
+}
+
+Fl_Widget *Fl_Navigation::value()
+{
+ int i;
+
+ for (i = 0;i < pages->children();i++) {
+ if (pages->child(i)->visible())
+ return pages->child(i);
+ }
+
+ return NULL;
+}
+
+int Fl_Navigation::value(Fl_Widget *newpage)
+{
+ int i;
+ int found;
+
+ assert(labels->children() == pages->children());
+
+ found = 0;
+ for (i = 0;i < pages->children();i++) {
+ if (pages->child(i) == newpage) {
+ pages->child(i)->show();
+ ((Fl_Button*)labels->child(i))->setonly();
+ found = 1;
+ } else {
+ pages->child(i)->hide();
+ }
+ }
+
+ return found;
+}
+
+void Fl_Navigation::client_area(int &rx, int &ry,
+ int &rw, int &rh, int lw)
+{
+ if (!pages->children()) {
+ int cx, cy, cw, ch;
+
+ cx = x() + 1;
+ cy = y() + 1;
+ cw = w() - 2;
+ ch = h() - 2;
+
+ scroll->resize(cx, cy, lw, ch);
+ labels->resize(cx, cy, lw, ch);
+ pages->resize(cx + lw + 1, cy, cw - lw - 1, ch);
+ }
+
+ rx = pages->x();
+ ry = pages->y();
+ rw = pages->w();
+ rh = pages->h();
+}
+
+void Fl_Navigation::draw()
+{
+ draw_box(FL_BORDER_FRAME, x(), y(),
+ labels->w()+2, h(), FL_DARK3);
+ draw_box(FL_BORDER_FRAME, x()+1+labels->w(), y(),
+ w() - (labels->w()+1), h(), FL_DARK3);
+ Fl_Group::draw();
+}
+
+void Fl_Navigation::begin()
+{
+ pages->begin();
+}
+
+void Fl_Navigation::end()
+{
+ pages->end();
+ Fl_Group::end();
+
+ update_labels();
+}
+
+void Fl_Navigation::update_labels()
+{
+ int i, offset;
+
+ labels->clear();
+ labels->resizable(NULL);
+
+ if (!pages->children())
+ return;
+
+ offset = 0;
+ for (i = 0;i < pages->children();i++) {
+ Fl_Widget *page;
+ Fl_Button *btn;
+
+ page = pages->child(i);
+
+ btn = new Fl_Button(labels->x(), labels->y() + offset,
+ labels->w(), page->labelsize() * 3,
+ page->label());
+ btn->box(FL_FLAT_BOX);
+ btn->type(FL_RADIO_BUTTON);
+ btn->color(FL_BACKGROUND2_COLOR);
+ btn->selection_color(FL_SELECTION_COLOR);
+ btn->labelsize(page->labelsize());
+ btn->labelfont(page->labelfont());
+ btn->image(page->image());
+ btn->deimage(page->deimage());
+ btn->callback(label_pressed, this);
+
+ labels->add(btn);
+ offset += page->labelsize() * 3;
+ }
+ labels->size(labels->w(), offset);
+
+ // FIXME: Retain selection
+ value(pages->child(0));
+}
+
+void Fl_Navigation::label_pressed(Fl_Widget *widget, void *user_data)
+{
+ Fl_Navigation *self = (Fl_Navigation *) user_data;
+
+ int i, idx;
+
+ idx = -1;
+ for (i = 0;i < self->labels->children();i++) {
+ if (self->labels->child(i) == widget)
+ idx = i;
+ }
+
+ assert(idx >= 0);
+ assert(idx < self->pages->children());
+
+ self->value(self->pages->child(idx));
+}
--- /dev/null
+/* Copyright 2022 Pierre Ossman for Cendio AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __FL_NAVIGATION_H__
+#define __FL_NAVIGATION_H__
+
+#include <FL/Fl_Group.H>
+
+class Fl_Scroll;
+
+class Fl_Navigation: private Fl_Group {
+public:
+ Fl_Navigation(int x, int y, int w, int h);
+ ~Fl_Navigation();
+
+ Fl_Widget *value();
+ int value(Fl_Widget*);
+
+ void client_area(int &rx, int &ry, int &rw, int &rh, int lw);
+
+ virtual void draw();
+
+ // Delegation to underlying widget
+ void begin();
+ void end();
+
+private:
+ void update_labels();
+
+ static void label_pressed(Fl_Widget *widget, void *user_data);
+
+private:
+ Fl_Scroll *scroll;
+ Fl_Group *labels;
+ Fl_Group *pages;
+};
+
+#endif