ReplicantStatusView.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /*
  2. * Copyright 2011-2012, Dario Casalinuovo. All rights reserved.
  3. * Distributed under the terms of the MIT License.
  4. *
  5. * Authors:
  6. * Dario Casalinuovo
  7. */
  8. #include "ReplicantStatusView.h"
  9. #include <stdio.h>
  10. #include <Application.h>
  11. #include <AppFileInfo.h>
  12. #include <Bitmap.h>
  13. #include <Catalog.h>
  14. #include <Deskbar.h>
  15. #include <IconUtils.h>
  16. #include <Message.h>
  17. #include <MenuField.h>
  18. #include <MenuItem.h>
  19. #include <PopUpMenu.h>
  20. #include <Roster.h>
  21. #include <Window.h>
  22. #include <libinterface/BitmapMenuItem.h>
  23. #include <libinterface/BitmapUtils.h>
  24. #include <libinterface/BitmapView.h>
  25. #include "AppMessages.h"
  26. #include "AppPreferences.h"
  27. #include "ChatOMatic.h"
  28. #include "ChatProtocolMessages.h"
  29. #include "ReplicantMenuItem.h"
  30. #include "Utils.h"
  31. #undef B_TRANSLATION_CONTEXT
  32. #define B_TRANSLATION_CONTEXT "ReplicantStatusView"
  33. extern "C" _EXPORT BView *instantiate_deskbar_item(void);
  34. // The following handler is added to the Deskbar's looper
  35. // to receive notifications from Caya
  36. class ReplicantHandler : public BHandler {
  37. public:
  38. ReplicantHandler(const char* name, ReplicantStatusView* target)
  39. :
  40. BHandler(name)
  41. {
  42. fTarget = target;
  43. }
  44. ~ReplicantHandler() {}
  45. virtual void MessageReceived(BMessage* message)
  46. {
  47. switch (message->what) {
  48. case IM_OWN_STATUS_SET:
  49. {
  50. int32 status;
  51. if (message->FindInt32("status", &status) != B_OK)
  52. return;
  53. fTarget->SetStatus((UserStatus)status);
  54. break;
  55. }
  56. default:
  57. BHandler::MessageReceived(message);
  58. }
  59. }
  60. private:
  61. ReplicantStatusView* fTarget;
  62. };
  63. ReplicantStatusView::ReplicantStatusView()
  64. :
  65. BView(BRect(0, 0, 15, 15), "ReplicantStatusView",
  66. B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW)
  67. {
  68. _Init();
  69. }
  70. ReplicantStatusView::ReplicantStatusView(BMessage* archive)
  71. :
  72. BView(archive)
  73. {
  74. _Init();
  75. }
  76. ReplicantStatusView::~ReplicantStatusView()
  77. {
  78. delete fCayaMsg;
  79. delete fReplicantHandler;
  80. delete fReplicantMenu;
  81. // TODO: Use a list for that
  82. // maybe our List wrapper to std::list
  83. delete fConnectingIcon;
  84. delete fIcon;
  85. delete fOfflineIcon;
  86. delete fBusyIcon;
  87. delete fAwayIcon;
  88. }
  89. void
  90. ReplicantStatusView::MessageReceived(BMessage* msg)
  91. {
  92. switch (msg->what) {
  93. case APP_REPLICANT_STATUS_SET:
  94. {
  95. int32 status;
  96. if (msg->FindInt32("status", &status) != B_OK)
  97. return;
  98. SetStatus((UserStatus)status);
  99. fCayaMsg->SendMessage(msg);
  100. break;
  101. }
  102. case APP_REPLICANT_EXIT:
  103. case APP_SHOW_SETTINGS:
  104. case APP_REPLICANT_SHOW_WINDOW:
  105. case APP_REPLICANT_MESSENGER:
  106. fCayaMsg->SendMessage(msg);
  107. break;
  108. default:
  109. BView::MessageReceived(msg);
  110. }
  111. }
  112. void
  113. ReplicantStatusView::SetStatus(UserStatus status)
  114. {
  115. for (int32 i = 0; i < fReplicantMenu->CountItems(); i++) {
  116. ReplicantMenuItem* item
  117. = dynamic_cast<ReplicantMenuItem*>(fReplicantMenu->ItemAt(i));
  118. if (item == NULL)
  119. continue;
  120. if (item->IsMarked())
  121. item->SetMarked(false);
  122. if (item && item->Status() == status && !item->IsCustom())
  123. item->SetMarked(true);
  124. }
  125. switch (status) {
  126. case STATUS_AWAY:
  127. fIcon = fAwayIcon;
  128. break;
  129. case STATUS_DO_NOT_DISTURB:
  130. fIcon = fBusyIcon;
  131. break;
  132. case STATUS_CUSTOM_STATUS:
  133. fIcon = fAppIcon;
  134. break;
  135. case STATUS_INVISIBLE:
  136. case STATUS_OFFLINE:
  137. fIcon = fOfflineIcon;
  138. break;
  139. default:
  140. fIcon = fIcon;
  141. break;
  142. }
  143. Invalidate();
  144. }
  145. // Draw our deskbar icon.
  146. void
  147. ReplicantStatusView::Draw(BRect rect)
  148. {
  149. SetDrawingMode(B_OP_ALPHA);
  150. DrawBitmap(fIcon);
  151. }
  152. ReplicantStatusView*
  153. ReplicantStatusView::Instantiate(BMessage* archive)
  154. {
  155. if (!validate_instantiation(archive, "ReplicantStatusView"))
  156. return NULL;
  157. return new ReplicantStatusView(archive);
  158. }
  159. status_t
  160. ReplicantStatusView::Archive(BMessage* archive, bool deep) const
  161. {
  162. status_t status = BView::Archive(archive, deep);
  163. if (status == B_OK)
  164. status = archive->AddString("add_on", APP_SIGNATURE);
  165. if (status == B_OK)
  166. status = archive->AddString("class", "ReplicantStatusView");
  167. return status;
  168. }
  169. void
  170. ReplicantStatusView::AttachedToWindow()
  171. {
  172. BView::AttachedToWindow();
  173. if (Parent())
  174. SetViewColor(Parent()->ViewColor());
  175. else
  176. SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
  177. SetLowColor(ViewColor());
  178. fReplicantHandler = new ReplicantHandler("CayaReplicantHandler", this);
  179. if (Window()->Lock()) {
  180. Window()->AddHandler(fReplicantHandler);
  181. Window()->Unlock();
  182. }
  183. BMessage msg(APP_REPLICANT_MESSENGER);
  184. BMessenger messenger(fReplicantHandler);
  185. if (!messenger.IsValid())
  186. return;
  187. msg.AddMessenger("messenger", messenger);
  188. fCayaMsg->SendMessage(&msg);
  189. }
  190. void
  191. ReplicantStatusView::DetachedFromWindow()
  192. {
  193. if (Window()->Lock()) {
  194. Window()->RemoveHandler(fReplicantHandler);
  195. Window()->Unlock();
  196. }
  197. }
  198. void
  199. ReplicantStatusView::MouseDown(BPoint point)
  200. {
  201. uint32 buttons;
  202. if (LockLooper()) {
  203. GetMouse(&point, &buttons, false);
  204. UnlockLooper();
  205. }
  206. if (buttons & B_PRIMARY_MOUSE_BUTTON) {
  207. // Show / Hide Window command
  208. BMessage msg(APP_REPLICANT_SHOW_WINDOW);
  209. fCayaMsg->SendMessage(&msg);
  210. } else if(buttons & B_SECONDARY_MOUSE_BUTTON) {
  211. // Build replicant menu
  212. _ShowMenu(point);
  213. }
  214. }
  215. void
  216. ReplicantStatusView::_Init()
  217. {
  218. SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
  219. // Creating the Send messenger and sending
  220. // a messenger targeting this to Caya.
  221. // This will allow the Replicant to communicate
  222. // whith Caya.
  223. fCayaMsg = new BMessenger(APP_SIGNATURE);
  224. fResources = ChatResources();
  225. //Get icons from resources
  226. fConnectingIcon = _GetIcon(kOnlineReplicant);
  227. fAppIcon = _GetIcon(kIconReplicant);
  228. fOfflineIcon = _GetIcon(kOfflineReplicant);
  229. fIcon = fOfflineIcon;
  230. fBusyIcon = _GetIcon(kBusyReplicant);
  231. fAwayIcon = _GetIcon(kAwayReplicant);
  232. fExitMenuIcon = _GetIcon(kExitMenuReplicant);
  233. fPreferencesIcon = _GetIcon(kToolIcon);
  234. // Build the replicant menu
  235. _BuildMenu();
  236. }
  237. BBitmap*
  238. ReplicantStatusView::_GetIcon(const uint32 id)
  239. {
  240. BBitmap* icon = IconFromResources(&fResources, id, B_MINI_ICON);
  241. return icon;
  242. }
  243. void
  244. ReplicantStatusView::_BuildMenu()
  245. {
  246. // Status menu
  247. fReplicantMenu = new BPopUpMenu(" - ", false, false);
  248. // Add status menu items
  249. int32 s = STATUS_ONLINE;
  250. while (s >= STATUS_ONLINE && s < STATUS_STATUSES) {
  251. BMessage* msg = new BMessage(APP_REPLICANT_STATUS_SET);
  252. msg->AddInt32("status", s);
  253. ReplicantMenuItem* item = new ReplicantMenuItem(
  254. UserStatusToString((UserStatus)s), (UserStatus)s);
  255. fReplicantMenu->AddItem(item);
  256. // Mark offline status by default
  257. if (s == STATUS_OFFLINE)
  258. item->SetMarked(true);
  259. s++;
  260. }
  261. fReplicantMenu->AddItem(new BSeparatorItem());
  262. fReplicantMenu->AddItem(new BitmapMenuItem(B_TRANSLATE("Preferences "),
  263. new BMessage(APP_SHOW_SETTINGS), fPreferencesIcon));
  264. fReplicantMenu->AddItem(new BitmapMenuItem(B_TRANSLATE("Exit"),
  265. new BMessage(APP_REPLICANT_EXIT), fExitMenuIcon));
  266. fReplicantMenu->SetTargetForItems(this);
  267. }
  268. void
  269. ReplicantStatusView::_ShowMenu(BPoint point)
  270. {
  271. fReplicantMenu->SetTargetForItems(this);
  272. ConvertToScreen(&point);
  273. fReplicantMenu->Go(point, true, true, true);
  274. }
  275. extern "C" _EXPORT BView *
  276. instantiate_deskbar_item(void)
  277. {
  278. return new ReplicantStatusView();
  279. }
  280. // The following methods install
  281. // and remove the Caya's replicant
  282. // from Deskbar.
  283. status_t
  284. ReplicantStatusView::InstallReplicant()
  285. {
  286. if (AppPreferences::Get()->DisableReplicant == true)
  287. return B_OK;
  288. BDeskbar deskbar;
  289. if (deskbar.HasItem("ReplicantStatusView")) {
  290. ReplicantStatusView::RemoveReplicant();
  291. }
  292. ReplicantStatusView* view = new ReplicantStatusView();
  293. return deskbar.AddItem(view);
  294. }
  295. status_t
  296. ReplicantStatusView::RemoveReplicant()
  297. {
  298. BDeskbar deskbar;
  299. return deskbar.RemoveItem("ReplicantStatusView");
  300. }