window.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. #if defined(Hiro_Window)
  2. mWindow::mWindow() {
  3. mObject::state.visible = false;
  4. }
  5. auto mWindow::allocate() -> pObject* {
  6. return new pWindow(*this);
  7. }
  8. auto mWindow::destruct() -> void {
  9. if(auto& menuBar = state.menuBar) menuBar->destruct();
  10. if(auto& sizable = state.sizable) sizable->destruct();
  11. if(auto& statusBar = state.statusBar) statusBar->destruct();
  12. mObject::destruct();
  13. }
  14. //
  15. auto mWindow::append(sMenuBar menuBar) -> type& {
  16. if(auto& menuBar = state.menuBar) remove(menuBar);
  17. menuBar->setParent(this, 0);
  18. state.menuBar = menuBar;
  19. signal(append, menuBar);
  20. return *this;
  21. }
  22. auto mWindow::append(sSizable sizable) -> type& {
  23. if(auto& sizable = state.sizable) remove(sizable);
  24. state.sizable = sizable;
  25. sizable->setParent(this, 0);
  26. signal(append, sizable);
  27. return *this;
  28. }
  29. auto mWindow::append(sStatusBar statusBar) -> type& {
  30. if(auto& statusBar = state.statusBar) remove(statusBar);
  31. statusBar->setParent(this, 0);
  32. state.statusBar = statusBar;
  33. signal(append, statusBar);
  34. return *this;
  35. }
  36. auto mWindow::backgroundColor() const -> Color {
  37. return state.backgroundColor;
  38. }
  39. auto mWindow::dismissable() const -> bool {
  40. return state.dismissable;
  41. }
  42. auto mWindow::doClose() const -> void {
  43. if(state.onClose) return state.onClose();
  44. }
  45. auto mWindow::doDrop(vector<string> names) const -> void {
  46. if(state.onDrop) return state.onDrop(names);
  47. }
  48. auto mWindow::doKeyPress(signed key) const -> void {
  49. if(state.onKeyPress) return state.onKeyPress(key);
  50. }
  51. auto mWindow::doKeyRelease(signed key) const -> void {
  52. if(state.onKeyRelease) return state.onKeyRelease(key);
  53. }
  54. auto mWindow::doMove() const -> void {
  55. if(state.onMove) return state.onMove();
  56. }
  57. auto mWindow::doSize() const -> void {
  58. if(state.onSize) return state.onSize();
  59. }
  60. auto mWindow::droppable() const -> bool {
  61. return state.droppable;
  62. }
  63. auto mWindow::frameGeometry() const -> Geometry {
  64. Geometry margin = signal(frameMargin);
  65. return {
  66. state.geometry.x() - margin.x(), state.geometry.y() - margin.y(),
  67. state.geometry.width() + margin.width(), state.geometry.height() + margin.height()
  68. };
  69. }
  70. auto mWindow::fullScreen() const -> bool {
  71. return state.fullScreen;
  72. }
  73. auto mWindow::geometry() const -> Geometry {
  74. return state.geometry;
  75. }
  76. auto mWindow::handle() const -> uintptr_t {
  77. return signal(handle);
  78. }
  79. auto mWindow::maximized() const -> bool {
  80. return state.maximized;
  81. }
  82. auto mWindow::maximumSize() const -> Size {
  83. return state.maximumSize;
  84. }
  85. auto mWindow::menuBar() const -> MenuBar {
  86. return state.menuBar;
  87. }
  88. auto mWindow::minimized() const -> bool {
  89. return state.minimized;
  90. }
  91. auto mWindow::minimumSize() const -> Size {
  92. return state.minimumSize;
  93. }
  94. auto mWindow::modal() const -> bool {
  95. return state.modal;
  96. }
  97. auto mWindow::monitor() const -> uint {
  98. return signal(monitor);
  99. }
  100. auto mWindow::onClose(const function<void ()>& callback) -> type& {
  101. state.onClose = callback;
  102. return *this;
  103. }
  104. auto mWindow::onDrop(const function<void (vector<string>)>& callback) -> type& {
  105. state.onDrop = callback;
  106. return *this;
  107. }
  108. auto mWindow::onKeyPress(const function<void (signed)>& callback) -> type& {
  109. state.onKeyPress = callback;
  110. return *this;
  111. }
  112. auto mWindow::onKeyRelease(const function<void (signed)>& callback) -> type& {
  113. state.onKeyRelease = callback;
  114. return *this;
  115. }
  116. auto mWindow::onMove(const function<void ()>& callback) -> type& {
  117. state.onMove = callback;
  118. return *this;
  119. }
  120. auto mWindow::onSize(const function<void ()>& callback) -> type& {
  121. state.onSize = callback;
  122. return *this;
  123. }
  124. auto mWindow::remove(sMenuBar menuBar) -> type& {
  125. signal(remove, menuBar);
  126. menuBar->setParent();
  127. state.menuBar.reset();
  128. return *this;
  129. }
  130. auto mWindow::remove(sSizable sizable) -> type& {
  131. signal(remove, sizable);
  132. sizable->setParent();
  133. state.sizable.reset();
  134. return *this;
  135. }
  136. auto mWindow::remove(sStatusBar statusBar) -> type& {
  137. signal(remove, statusBar);
  138. statusBar->setParent();
  139. state.statusBar.reset();
  140. return *this;
  141. }
  142. auto mWindow::reset() -> type& {
  143. if(auto& menuBar = state.menuBar) remove(menuBar);
  144. if(auto& sizable = state.sizable) remove(sizable);
  145. if(auto& statusBar = state.statusBar) remove(statusBar);
  146. return *this;
  147. }
  148. auto mWindow::resizable() const -> bool {
  149. return state.resizable;
  150. }
  151. auto mWindow::setAlignment(Alignment alignment) -> type& {
  152. auto workspace = Monitor::workspace();
  153. auto geometry = frameGeometry();
  154. auto x = workspace.x() + alignment.horizontal() * (workspace.width() - geometry.width());
  155. auto y = workspace.y() + alignment.vertical() * (workspace.height() - geometry.height());
  156. setFramePosition({(int)x, (int)y});
  157. return *this;
  158. }
  159. auto mWindow::setAlignment(sWindow relativeTo, Alignment alignment) -> type& {
  160. if(!relativeTo) return setAlignment(alignment);
  161. auto parent = relativeTo->frameGeometry();
  162. auto window = frameGeometry();
  163. //+0 .. +1 => within parent window
  164. auto x = parent.x() + (parent.width() - window.width()) * alignment.horizontal();
  165. auto y = parent.y() + (parent.height() - window.height()) * alignment.vertical();
  166. //-1 .. -0 => beyond parent window
  167. //... I know, relying on -0 IEE754 here is ... less than ideal
  168. if(signbit(alignment.horizontal())) {
  169. x = (parent.x() - window.width()) + abs(alignment.horizontal()) * (parent.width() + window.width());
  170. }
  171. if(signbit(alignment.vertical())) {
  172. y = (parent.y() - window.height()) + abs(alignment.vertical()) * (parent.height() + window.height());
  173. }
  174. setFramePosition({(int)x, (int)y});
  175. return *this;
  176. }
  177. auto mWindow::setBackgroundColor(Color color) -> type& {
  178. state.backgroundColor = color;
  179. signal(setBackgroundColor, color);
  180. return *this;
  181. }
  182. auto mWindow::setDismissable(bool dismissable) -> type& {
  183. state.dismissable = dismissable;
  184. signal(setDismissable, dismissable);
  185. return *this;
  186. }
  187. auto mWindow::setDroppable(bool droppable) -> type& {
  188. state.droppable = droppable;
  189. signal(setDroppable, droppable);
  190. return *this;
  191. }
  192. auto mWindow::setFrameGeometry(Geometry geometry) -> type& {
  193. Geometry margin = signal(frameMargin);
  194. return setGeometry({
  195. geometry.x() + margin.x(), geometry.y() + margin.y(),
  196. geometry.width() - margin.width(), geometry.height() - margin.height()
  197. });
  198. }
  199. auto mWindow::setFramePosition(Position position) -> type& {
  200. Geometry margin = signal(frameMargin);
  201. return setGeometry({
  202. position.x() + margin.x(), position.y() + margin.y(),
  203. state.geometry.width(), state.geometry.height()
  204. });
  205. }
  206. auto mWindow::setFrameSize(Size size) -> type& {
  207. Geometry margin = signal(frameMargin);
  208. return setGeometry({
  209. state.geometry.x(), state.geometry.y(),
  210. size.width() - margin.width(), size.height() - margin.height()
  211. });
  212. }
  213. auto mWindow::setFullScreen(bool fullScreen) -> type& {
  214. if(fullScreen != state.fullScreen) {
  215. state.fullScreen = fullScreen;
  216. signal(setFullScreen, fullScreen);
  217. }
  218. return *this;
  219. }
  220. auto mWindow::setGeometry(Geometry geometry) -> type& {
  221. //round fractional bits of geometry coordinates that window managers cannot display.
  222. //the pWindow classes lose this precision and so not doing so here can cause off-by-1 issues.
  223. geometry.setX(round(geometry.x()));
  224. geometry.setY(round(geometry.y()));
  225. geometry.setWidth(round(geometry.width()));
  226. geometry.setHeight(round(geometry.height()));
  227. state.geometry = geometry;
  228. signal(setGeometry, geometry);
  229. if(auto& sizable = state.sizable) sizable->setGeometry(sizable->geometry());
  230. return *this;
  231. }
  232. auto mWindow::setGeometry(Alignment alignment, Size size) -> type& {
  233. auto margin = signal(frameMargin);
  234. auto width = margin.width() + size.width();
  235. auto height = margin.height() + size.height();
  236. auto workspace = Monitor::workspace();
  237. auto x = workspace.x() + alignment.horizontal() * (workspace.width() - width);
  238. auto y = workspace.y() + alignment.vertical() * (workspace.height() - height);
  239. setFrameGeometry({(int)x, (int)y, (int)width, (int)height});
  240. return *this;
  241. }
  242. auto mWindow::setMaximized(bool maximized) -> type& {
  243. state.maximized = maximized;
  244. signal(setMaximized, maximized);
  245. return *this;
  246. }
  247. auto mWindow::setMaximumSize(Size size) -> type& {
  248. state.maximumSize = size;
  249. signal(setMaximumSize, size);
  250. return *this;
  251. }
  252. auto mWindow::setMinimized(bool minimized) -> type& {
  253. state.minimized = minimized;
  254. signal(setMinimized, minimized);
  255. return *this;
  256. }
  257. auto mWindow::setMinimumSize(Size size) -> type& {
  258. state.minimumSize = size;
  259. signal(setMinimumSize, size);
  260. return *this;
  261. }
  262. auto mWindow::setModal(bool modal) -> type& {
  263. if(state.modal == modal) return *this;
  264. state.modal = modal;
  265. if(modal) {
  266. Application::state().modal++;
  267. } else {
  268. Application::state().modal--;
  269. assert(Application::state().modal >= 0);
  270. }
  271. signal(setModal, modal);
  272. return *this;
  273. }
  274. auto mWindow::setPosition(Position position) -> type& {
  275. return setGeometry({
  276. position.x(), position.y(),
  277. state.geometry.width(), state.geometry.height()
  278. });
  279. }
  280. auto mWindow::setPosition(sWindow relativeTo, Position position) -> type& {
  281. if(!relativeTo) return setPosition(position);
  282. auto geometry = relativeTo->frameGeometry();
  283. return setFramePosition({
  284. geometry.x() + position.x(),
  285. geometry.y() + position.y()
  286. });
  287. }
  288. auto mWindow::setResizable(bool resizable) -> type& {
  289. state.resizable = resizable;
  290. signal(setResizable, resizable);
  291. return *this;
  292. }
  293. auto mWindow::setSize(Size size) -> type& {
  294. return setGeometry({
  295. state.geometry.x(), state.geometry.y(),
  296. size.width(), size.height()
  297. });
  298. }
  299. auto mWindow::setTitle(const string& title) -> type& {
  300. state.title = title;
  301. signal(setTitle, title);
  302. return *this;
  303. }
  304. auto mWindow::setVisible(bool visible) -> type& {
  305. mObject::setVisible(visible);
  306. if(auto& menuBar = state.menuBar) menuBar->setVisible(menuBar->visible());
  307. if(auto& sizable = state.sizable) sizable->setVisible(sizable->visible());
  308. if(auto& statusBar = state.statusBar) statusBar->setVisible(statusBar->visible());
  309. return *this;
  310. }
  311. auto mWindow::sizable() const -> Sizable {
  312. return state.sizable;
  313. }
  314. auto mWindow::statusBar() const -> StatusBar {
  315. return state.statusBar;
  316. }
  317. auto mWindow::title() const -> string {
  318. return state.title;
  319. }
  320. #endif