1 /*************************************************************************** 2 * Copyright (C) 2008-2021 by Andrzej Rybczak * 3 * andrzej@rybczak.net * 4 * * 5 * This program is free software; you can redistribute it and/or modify * 6 * it under the terms of the GNU General Public License as published by * 7 * the Free Software Foundation; either version 2 of the License, or * 8 * (at your option) any later version. * 9 * * 10 * This program is distributed in the hope that it will be useful, * 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 * GNU General Public License for more details. * 14 * * 15 * You should have received a copy of the GNU General Public License * 16 * along with this program; if not, write to the * 17 * Free Software Foundation, Inc., * 18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * 19 ***************************************************************************/ 20 21 #ifndef NCMPCPP_SCREEN_H 22 #define NCMPCPP_SCREEN_H 23 24 #include "curses/menu.h" 25 #include "curses/scrollpad.h" 26 #include "screens/screen_type.h" 27 28 void drawSeparator(int x); 29 void genericMouseButtonPressed(NC::Window &w, MEVENT me); 30 void scrollpadMouseButtonPressed(NC::Scrollpad &w, MEVENT me); 31 32 /// An interface for various instantiations of Screen template class. Since C++ doesn't like 33 /// comparison of two different instantiations of the same template class we need the most 34 /// basic class to be non-template to allow it. 35 struct BaseScreen 36 { BaseScreenBaseScreen37 BaseScreen() : hasToBeResized(false) { } ~BaseScreenBaseScreen38 virtual ~BaseScreen() { } 39 40 /// @see Screen::isActiveWindow() 41 virtual bool isActiveWindow(const NC::Window &w_) const = 0; 42 43 /// @see Screen::activeWindow() 44 virtual NC::Window *activeWindow() = 0; 45 virtual const NC::Window *activeWindow() const = 0; 46 47 /// @see Screen::refresh() 48 virtual void refresh() = 0; 49 50 /// @see Screen::refreshWindow() 51 virtual void refreshWindow() = 0; 52 53 /// @see Screen::scroll() 54 virtual void scroll(NC::Scroll where) = 0; 55 56 /// Method used for switching to screen 57 virtual void switchTo() = 0; 58 59 /// Method that should resize screen 60 /// if requested by hasToBeResized 61 virtual void resize() = 0; 62 63 /// @return ncurses timeout parameter for the screen 64 virtual int windowTimeout() = 0; 65 66 /// @return title of the screen 67 virtual std::wstring title() = 0; 68 69 /// @return type of the screen 70 virtual ScreenType type() = 0; 71 72 /// If the screen contantly has to update itself 73 /// somehow, it should be called by this function. 74 virtual void update() = 0; 75 76 /// @see Screen::mouseButtonPressed() 77 virtual void mouseButtonPressed(MEVENT me) = 0; 78 79 /// @return true if screen can be locked. Note that returning 80 /// false here doesn't neccesarily mean that screen is also not 81 /// mergable (eg. lyrics screen is not lockable since that wouldn't 82 /// make much sense, but it's perfectly fine to merge it). 83 virtual bool isLockable() = 0; 84 85 /// @return true if screen is mergable, ie. can be "proper" subwindow 86 /// if one of the screens is locked. Screens that somehow resemble popups 87 /// will want to return false here. 88 virtual bool isMergable() = 0; 89 90 /// Locks current screen. 91 /// @return true if lock was successful, false otherwise. Note that 92 /// if there is already locked screen, it'll not overwrite it. 93 bool lock(); 94 95 /// Should be set to true each time screen needs resize 96 bool hasToBeResized; 97 98 /// Unlocks a screen, ie. hides merged window (if there is one set). 99 static void unlock(); 100 101 const static int defaultWindowTimeout = 500; 102 103 protected: 104 /// Gets X offset and width of current screen to be used eg. in resize() function. 105 /// @param adjust_locked_screen indicates whether this function should 106 /// automatically adjust locked screen's dimensions (if there is one set) 107 /// if current screen is going to be subwindow. 108 void getWindowResizeParams(size_t &x_offset, size_t &width, bool adjust_locked_screen = true); 109 }; 110 111 void applyToVisibleWindows(std::function<void(BaseScreen *)> f); 112 void updateInactiveScreen(BaseScreen *screen_to_be_set); 113 bool isVisible(BaseScreen *screen); 114 115 /// Class that all screens should derive from. It provides basic interface 116 /// for the screen to be working properly and assumes that we didn't forget 117 /// about anything vital. 118 /// 119 template <typename WindowT> struct Screen : public BaseScreen 120 { 121 typedef WindowT WindowType; 122 typedef typename std::add_lvalue_reference< 123 WindowType 124 >::type WindowReference; 125 typedef typename std::add_lvalue_reference< 126 typename std::add_const<WindowType>::type 127 >::type ConstWindowReference; 128 129 private: 130 template <bool IsPointer, typename Result, typename ConstResult> 131 struct getObject { applyScreen::getObject132 static Result &apply(WindowReference w) { return w; } constApplyScreen::getObject133 static ConstResult &constApply(ConstWindowReference w) { return w; } 134 }; 135 template <typename Result, typename ConstResult> 136 struct getObject<true, Result, ConstResult> { 137 static Result &apply(WindowType w) { return *w; } 138 static ConstResult &constApply(const WindowType w) { return *w; } 139 }; 140 141 typedef getObject< 142 std::is_pointer<WindowT>::value, 143 typename std::remove_pointer<WindowT>::type, 144 typename std::add_const< 145 typename std::remove_pointer<WindowT>::type 146 >::type 147 > Accessor; 148 149 public: 150 Screen() { } 151 Screen(WindowT w_) : w(w_) { } 152 153 virtual ~Screen() { } 154 155 virtual bool isActiveWindow(const NC::Window &w_) const override { 156 return &Accessor::constApply(w) == &w_; 157 } 158 159 /// Since some screens contain more that one window 160 /// it's useful to determine the one that is being 161 /// active 162 /// @return address to window object cast to void * 163 virtual NC::Window *activeWindow() override { 164 return &Accessor::apply(w); 165 } 166 virtual const NC::Window *activeWindow() const override { 167 return &Accessor::constApply(w); 168 } 169 170 /// Refreshes whole screen 171 virtual void refresh() override { 172 Accessor::apply(w).display(); 173 } 174 175 /// Refreshes active window of the screen 176 virtual void refreshWindow() override { 177 Accessor::apply(w).display(); 178 } 179 180 /// Scrolls the screen by given amount of lines and 181 /// if fancy scrolling feature is disabled, enters the 182 /// loop that holds main loop until user releases the key 183 /// @param where indicates where one wants to scroll 184 virtual void scroll(NC::Scroll where) override { 185 Accessor::apply(w).scroll(where); 186 } 187 188 /// @return timeout parameter used for the screen (in ms) 189 /// @default defaultWindowTimeout 190 virtual int windowTimeout() override { 191 return defaultWindowTimeout; 192 } 193 194 /// Invoked after there was one of mouse buttons pressed 195 /// @param me struct that contains coords of where the click 196 /// had its place and button actions 197 virtual void mouseButtonPressed(MEVENT me) override { 198 genericMouseButtonPressed(Accessor::apply(w), me); 199 } 200 201 /// @return currently active window 202 WindowReference main() { 203 return w; 204 } 205 ConstWindowReference main() const { 206 return w; 207 } 208 209 protected: 210 /// Template parameter that should indicate the main type 211 /// of window used by the screen. What is more, it should 212 /// always be assigned to the currently active window (if 213 /// acreen contains more that one) 214 WindowT w; 215 }; 216 217 /// Specialization for Screen<Scrollpad>::mouseButtonPressed that should 218 /// not scroll whole page, but rather a few lines (the number of them is 219 /// defined in the config) 220 template <> inline void Screen<NC::Scrollpad>::mouseButtonPressed(MEVENT me) { 221 scrollpadMouseButtonPressed(w, me); 222 } 223 224 #endif // NCMPCPP_SCREEN_H 225 226