1 /**
2  * Copyright (c) 2007-2012, Timothy Stack
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  * * Neither the name of Timothy Stack nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * @file statusview_curses.hh
30  */
31 
32 #ifndef statusview_curses_hh
33 #define statusview_curses_hh
34 
35 #include <string>
36 #include <vector>
37 
38 #include "view_curses.hh"
39 #include "ansi_scrubber.hh"
40 
41 /**
42  * Container for individual status values.
43  */
44 class status_field {
45 public:
46 
47     /**
48      * @param width The maximum width of the field in characters.
49      * @param role The color role for this field, defaults to VCR_STATUS.
50      */
status_field(int width=1,view_colors::role_t role=view_colors::VCR_STATUS)51     status_field(int width = 1,
52                  view_colors::role_t role = view_colors::VCR_STATUS)
53         : sf_width(width),
54           sf_role(role) {
55     };
56 
57     virtual ~status_field() = default;
58 
59     /** @param value The new value for this field. */
60     void set_value(std::string value);
61 
62     /**
63      * Set the new value for this field using a formatted string.
64      *
65      * @param fmt The format string.
66      * @param ... Arguments for the format.
67      */
set_value(const char * fmt,...)68     status_field& set_value(const char *fmt, ...)
69     {
70         char    buffer[256];
71         va_list args;
72 
73         va_start(args, fmt);
74         vsnprintf(buffer, sizeof(buffer), fmt, args);
75         this->set_value(std::string(buffer));
76         va_end(args);
77 
78         return *this;
79     };
80 
81     void set_stitch_value(view_colors::role_t left, view_colors::role_t right);
82 
set_left_pad(size_t val)83     void set_left_pad(size_t val) { this->sf_left_pad = val; };
get_left_pad() const84     size_t get_left_pad() const { return this->sf_left_pad; };
85 
86     /** @return The string value for this field. */
get_value()87     attr_line_t &get_value() { return this->sf_value; };
88 
right_justify(bool yes)89     void right_justify(bool yes) { this->sf_right_justify = yes; };
is_right_justified() const90     bool is_right_justified() const { return this->sf_right_justify; };
91 
set_cylon(bool yes)92     status_field& set_cylon(bool yes) {
93         this->sf_cylon = yes;
94         return *this;
95     };
is_cylon() const96     bool is_cylon() const { return this->sf_cylon; };
97 
98     void do_cylon();
99 
100     /** @return True if this field's value is an empty string. */
empty() const101     bool empty() const { return this->sf_value.get_string().empty(); };
102 
clear()103     void clear() { this->sf_value.clear(); };
104 
105     /** @param role The color role for this field. */
set_role(view_colors::role_t role)106     void set_role(view_colors::role_t role) { this->sf_role = role; };
107     /** @return The color role for this field. */
get_role() const108     view_colors::role_t get_role() const { return this->sf_role; };
109 
110     /** @param width The maximum display width, in characters. */
set_width(ssize_t width)111     void set_width(ssize_t width) { this->sf_width = width; };
112     /** @param width The maximum display width, in characters. */
get_width() const113     ssize_t get_width() const { return this->sf_width; };
114 
115     /** @param width The maximum display width, in characters. */
set_min_width(int width)116     void set_min_width(int width) { this->sf_min_width = width; };
117     /** @param width The maximum display width, in characters. */
get_min_width() const118     size_t get_min_width() const { return this->sf_min_width; };
119 
set_share(int share)120     void set_share(int share) { this->sf_share = share; };
get_share() const121     int get_share() const { return this->sf_share; };
122 
123 protected:
124     ssize_t             sf_width;     /*< The maximum display width, in chars. */
125     ssize_t             sf_min_width{0}; /*< The minimum display width, in chars. */
126     bool                sf_right_justify{false};
127     bool                sf_cylon{false};
128     ssize_t             sf_cylon_pos{0};
129     attr_line_t         sf_value; /*< The value to display for this field. */
130     view_colors::role_t sf_role;  /*< The color role for this field. */
131     int sf_share{0};
132     size_t sf_left_pad{0};
133 };
134 
135 /**
136  * Data source for the fields to be displayed in a status view.
137  */
138 class status_data_source {
139 public:
140     virtual ~status_data_source() = default;
141 
142     /**
143      * @return The number of status_fields in this source.
144      */
145     virtual size_t statusview_fields() = 0;
146 
147     /**
148      * Callback used to get a particular field.
149      *
150      * @param field The index of the field to return.
151      * @return A reference to the field at the given index.
152      */
153     virtual status_field &statusview_value_for_field(int field) = 0;
154 };
155 
156 /**
157  * A view that displays a collection of fields in a line on the display.
158  */
159 class statusview_curses
160     : public view_curses {
161 public:
set_data_source(status_data_source * src)162     void set_data_source(status_data_source *src) { this->sc_source = src; };
get_data_source()163     status_data_source *get_data_source() { return this->sc_source; };
164 
set_top(int top)165     void set_top(int top) { this->sc_top = top; };
get_top() const166     int get_top() const { return this->sc_top; };
167 
set_window(WINDOW * win)168     void set_window(WINDOW *win) { this->sc_window = win; };
get_window()169     WINDOW *get_window() { return this->sc_window; };
170 
set_enabled(bool value)171     void set_enabled(bool value) { this->sc_enabled = value; };
get_enabled() const172     bool get_enabled() const { return this->sc_enabled; };
173 
174     void window_change();
175 
176     void do_update() override;
177 
178 private:
179     status_data_source *sc_source{nullptr};
180     WINDOW *            sc_window{nullptr};
181     int sc_top{0};
182     unsigned long sc_last_width{0};
183     bool sc_enabled{true};
184 };
185 
186 #endif
187