1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 /*
7
8 This file provides the implementation for the XUL "controllers"
9 object.
10
11 */
12
13 #include "nsString.h"
14
15 #include "nsIControllers.h"
16 #include "nsXULControllers.h"
17 #include "nsIController.h"
18 #include "mozilla/RefPtr.h"
19
20 //----------------------------------------------------------------------
21
nsXULControllerData(uint32_t inControllerID,nsIController * inController)22 nsXULControllerData::nsXULControllerData(uint32_t inControllerID,
23 nsIController* inController)
24 : mControllerID(inControllerID), mController(inController) {}
25
GetController(nsIController ** outController)26 nsresult nsXULControllerData::GetController(nsIController** outController) {
27 NS_IF_ADDREF(*outController = mController);
28 return NS_OK;
29 }
30
nsXULControllers()31 nsXULControllers::nsXULControllers() : mCurControllerID(0) {}
32
~nsXULControllers(void)33 nsXULControllers::~nsXULControllers(void) { DeleteControllers(); }
34
DeleteControllers()35 void nsXULControllers::DeleteControllers() {
36 uint32_t count = mControllers.Length();
37 for (uint32_t i = 0; i < count; i++) {
38 nsXULControllerData* controllerData = mControllers.ElementAt(i);
39 delete controllerData; // releases the nsIController
40 }
41
42 mControllers.Clear();
43 }
44
45 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULControllers)
46
47 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULControllers)
48 tmp->DeleteControllers();
49 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULControllers)50 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULControllers)
51 {
52 uint32_t i, count = tmp->mControllers.Length();
53 for (i = 0; i < count; ++i) {
54 nsXULControllerData* controllerData = tmp->mControllers[i];
55 if (controllerData) {
56 cb.NoteXPCOMChild(controllerData->mController);
57 }
58 }
59 }
60 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
61
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULControllers)62 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULControllers)
63 NS_INTERFACE_MAP_ENTRY(nsIControllers)
64 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIControllers)
65 NS_INTERFACE_MAP_END
66
67 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULControllers)
68 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULControllers)
69
70 NS_IMETHODIMP
71 nsXULControllers::GetControllerForCommand(const char* aCommand,
72 nsIController** _retval) {
73 NS_ENSURE_ARG_POINTER(_retval);
74 *_retval = nullptr;
75
76 uint32_t count = mControllers.Length();
77 for (uint32_t i = 0; i < count; i++) {
78 nsXULControllerData* controllerData = mControllers.ElementAt(i);
79 if (controllerData) {
80 nsCOMPtr<nsIController> controller;
81 controllerData->GetController(getter_AddRefs(controller));
82 if (controller) {
83 bool supportsCommand;
84 controller->SupportsCommand(aCommand, &supportsCommand);
85 if (supportsCommand) {
86 controller.forget(_retval);
87 return NS_OK;
88 }
89 }
90 }
91 }
92
93 return NS_OK;
94 }
95
96 NS_IMETHODIMP
InsertControllerAt(uint32_t aIndex,nsIController * controller)97 nsXULControllers::InsertControllerAt(uint32_t aIndex,
98 nsIController* controller) {
99 nsXULControllerData* controllerData =
100 new nsXULControllerData(++mCurControllerID, controller);
101 #ifdef DEBUG
102 nsXULControllerData** inserted =
103 #endif
104 mControllers.InsertElementAt(aIndex, controllerData);
105 NS_ASSERTION(inserted != nullptr, "Insertion of controller failed");
106 return NS_OK;
107 }
108
109 NS_IMETHODIMP
RemoveControllerAt(uint32_t aIndex,nsIController ** _retval)110 nsXULControllers::RemoveControllerAt(uint32_t aIndex, nsIController** _retval) {
111 NS_ENSURE_ARG_POINTER(_retval);
112 *_retval = nullptr;
113
114 nsXULControllerData* controllerData = mControllers.SafeElementAt(aIndex);
115 if (!controllerData) return NS_ERROR_FAILURE;
116
117 mControllers.RemoveElementAt(aIndex);
118
119 controllerData->GetController(_retval);
120 delete controllerData;
121
122 return NS_OK;
123 }
124
125 NS_IMETHODIMP
GetControllerAt(uint32_t aIndex,nsIController ** _retval)126 nsXULControllers::GetControllerAt(uint32_t aIndex, nsIController** _retval) {
127 NS_ENSURE_ARG_POINTER(_retval);
128 *_retval = nullptr;
129
130 nsXULControllerData* controllerData = mControllers.SafeElementAt(aIndex);
131 if (!controllerData) return NS_ERROR_FAILURE;
132
133 return controllerData->GetController(_retval); // does the addref
134 }
135
136 NS_IMETHODIMP
AppendController(nsIController * controller)137 nsXULControllers::AppendController(nsIController* controller) {
138 // This assigns controller IDs starting at 1 so we can use 0 to test if an ID
139 // was obtained
140 nsXULControllerData* controllerData =
141 new nsXULControllerData(++mCurControllerID, controller);
142
143 #ifdef DEBUG
144 nsXULControllerData** appended =
145 #endif
146 mControllers.AppendElement(controllerData);
147 NS_ASSERTION(appended != nullptr, "Appending controller failed");
148 return NS_OK;
149 }
150
151 NS_IMETHODIMP
RemoveController(nsIController * controller)152 nsXULControllers::RemoveController(nsIController* controller) {
153 // first get the identity pointer
154 nsCOMPtr<nsISupports> controllerSup(do_QueryInterface(controller));
155 // then find it
156 uint32_t count = mControllers.Length();
157 for (uint32_t i = 0; i < count; i++) {
158 nsXULControllerData* controllerData = mControllers.ElementAt(i);
159 if (controllerData) {
160 nsCOMPtr<nsIController> thisController;
161 controllerData->GetController(getter_AddRefs(thisController));
162 nsCOMPtr<nsISupports> thisControllerSup(
163 do_QueryInterface(thisController)); // get identity
164 if (thisControllerSup == controllerSup) {
165 mControllers.RemoveElementAt(i);
166 delete controllerData;
167 return NS_OK;
168 }
169 }
170 }
171 return NS_ERROR_FAILURE; // right thing to return if no controller found?
172 }
173
174 NS_IMETHODIMP
GetControllerId(nsIController * controller,uint32_t * _retval)175 nsXULControllers::GetControllerId(nsIController* controller,
176 uint32_t* _retval) {
177 NS_ENSURE_ARG_POINTER(_retval);
178
179 uint32_t count = mControllers.Length();
180 for (uint32_t i = 0; i < count; i++) {
181 nsXULControllerData* controllerData = mControllers.ElementAt(i);
182 if (controllerData) {
183 nsCOMPtr<nsIController> thisController;
184 controllerData->GetController(getter_AddRefs(thisController));
185 if (thisController.get() == controller) {
186 *_retval = controllerData->GetControllerID();
187 return NS_OK;
188 }
189 }
190 }
191 return NS_ERROR_FAILURE; // none found
192 }
193
194 NS_IMETHODIMP
GetControllerById(uint32_t controllerID,nsIController ** _retval)195 nsXULControllers::GetControllerById(uint32_t controllerID,
196 nsIController** _retval) {
197 NS_ENSURE_ARG_POINTER(_retval);
198
199 uint32_t count = mControllers.Length();
200 for (uint32_t i = 0; i < count; i++) {
201 nsXULControllerData* controllerData = mControllers.ElementAt(i);
202 if (controllerData && controllerData->GetControllerID() == controllerID) {
203 return controllerData->GetController(_retval);
204 }
205 }
206 return NS_ERROR_FAILURE; // none found
207 }
208
209 NS_IMETHODIMP
GetControllerCount(uint32_t * _retval)210 nsXULControllers::GetControllerCount(uint32_t* _retval) {
211 NS_ENSURE_ARG_POINTER(_retval);
212 *_retval = mControllers.Length();
213 return NS_OK;
214 }
215