]> source.dussan.org Git - tigervnc.git/commitdiff
Change to modern layout in options dialog
authorPierre Ossman <ossman@cendio.se>
Fri, 14 Jan 2022 13:07:19 +0000 (14:07 +0100)
committerPierre Ossman <ossman@cendio.se>
Thu, 22 Dec 2022 12:36:10 +0000 (13:36 +0100)
Classical tabs are very dated. They are also a practical problem as you
get very limited in the numbers of tabs we can have, and how long the
text can be on them.

Switch to one popular modern model with a list on the left instead where
pages can be selected.

vncviewer/CMakeLists.txt
vncviewer/OptionsDialog.cxx
vncviewer/fltk/Fl_Navigation.cxx [new file with mode: 0644]
vncviewer/fltk/Fl_Navigation.h [new file with mode: 0644]
vncviewer/fltk/layout.h

index 0e1b27b8c980f8838c540fe4de97d7048740ee82..1a4f9f1303149c0d6bfab97d1fca9b731c80f071 100644 (file)
@@ -5,6 +5,7 @@ include_directories(${CMAKE_SOURCE_DIR}/common)
 
 add_executable(vncviewer
   fltk/Fl_Monitor_Arrangement.cxx
+  fltk/Fl_Navigation.cxx
   fltk/theme.cxx
   menukey.cxx
   BaseTouchHandler.cxx
index 22224a9b6589b4a7f6ee84a0bf277cf0ce5220b2..dcb8ca0936ab800448b110ae5695430756baf3c1 100644 (file)
@@ -43,6 +43,7 @@
 #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>
@@ -62,19 +63,26 @@ std::map<OptionsCallback*, void*> OptionsDialog::callbacks;
 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);
@@ -83,7 +91,7 @@ OptionsDialog::OptionsDialog()
     createMiscPage(tx, ty, tw, th);
   }
 
-  tabs->end();
+  navigation->end();
 
   x = w() - BUTTON_WIDTH * 2 - INNER_MARGIN - OUTER_MARGIN;
   y = h() - BUTTON_HEIGHT - OUTER_MARGIN;
@@ -1006,7 +1014,7 @@ void OptionsDialog::createDisplayPage(int tx, int ty, int tw, int th)
 
 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;
diff --git a/vncviewer/fltk/Fl_Navigation.cxx b/vncviewer/fltk/Fl_Navigation.cxx
new file mode 100644 (file)
index 0000000..603c69c
--- /dev/null
@@ -0,0 +1,198 @@
+/* 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));
+}
diff --git a/vncviewer/fltk/Fl_Navigation.h b/vncviewer/fltk/Fl_Navigation.h
new file mode 100644 (file)
index 0000000..7f5e44a
--- /dev/null
@@ -0,0 +1,58 @@
+/* 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
index ae716e1a7d247a0a3b7ccabd37369ada00ebb5bc..31d6a65083337e99ed91b90b0e92b28ed64f09e7 100644 (file)
@@ -51,9 +51,6 @@ static inline int gui_str_len(const char *str)
 
 /**** FLTK WIDGETS ****/
 
-/* Fl_Tabs */
-#define TABS_HEIGHT             30
-
 /* Fl_Input */
 #define INPUT_LABEL_OFFSET      FL_NORMAL_SIZE
 #define INPUT_HEIGHT            25