Back to index

lightning-sunbird  0.9+nobinonly
nsMaiInterfaceAction.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* vim:expandtab:shiftwidth=4:tabstop=4:
00003  */
00004 /* ***** BEGIN LICENSE BLOCK *****
00005  * Version: NPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  *
00008  * The contents of this file are subject to the Mozilla Public
00009  * License Version 1.1 (the "License"); you may not use this file
00010  * except in compliance with the License. You may obtain a copy of
00011  * the License at http://www.mozilla.org/MPL/
00012  *
00013  * Software distributed under the License is distributed on an "AS
00014  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
00015  * implied. See the License for the specific language governing
00016  * rights and limitations under the License.
00017  *
00018  * The Original Code is mozilla.org code.
00019  *
00020  * The Initial Developer of the Original Code is Sun Microsystems, Inc.
00021  * Portions created by Sun Microsystems are Copyright (C) 2002 Sun
00022  * Microsystems, Inc. All Rights Reserved.
00023  *
00024  * Original Author: Bolian Yin (bolian.yin@sun.com)
00025  *
00026  * Contributor(s):
00027  *
00028  * Alternatively, the contents of this file may be used under the terms of
00029  * either the GNU General Public License Version 2 or later (the "GPL"), or
00030  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00031  * in which case the provisions of the GPL or the LGPL are applicable instead
00032  * of those above. If you wish to allow use of your version of this file only
00033  * under the terms of either the GPL or the LGPL, and not to allow others to
00034  * use your version of this file under the terms of the NPL, indicate your
00035  * decision by deleting the provisions above and replace them with the notice
00036  * and other provisions required by the GPL or the LGPL. If you do not delete
00037  * the provisions above, a recipient may use your version of this file under
00038  * the terms of any one of the NPL, the GPL or the LGPL.
00039  *
00040  * ***** END LICENSE BLOCK ***** */
00041 
00042 #include "nsMaiInterfaceAction.h"
00043 #include "nsAccessibleWrap.h"
00044 #include "nsString.h"
00045 
00046 G_BEGIN_DECLS
00047 
00048 static void interfaceInitCB(AtkActionIface *aIface);
00049 /* action interface callbacks */
00050 static gboolean doActionCB(AtkAction *aAction, gint aActionIndex);
00051 static gint getActionCountCB(AtkAction *aAction);
00052 static const gchar *getDescriptionCB(AtkAction *aAction, gint aActionIndex);
00053 static const gchar *getNameCB(AtkAction *aAction, gint aActionIndex);
00054 static const gchar *getKeyBindingCB(AtkAction *aAction, gint aActionIndex);
00055 static gboolean     setDescriptionCB(AtkAction *aAction, gint aActionIndex,
00056                                      const gchar *aDesc);
00057 G_END_DECLS
00058 
00059 MaiInterfaceAction::MaiInterfaceAction(nsAccessibleWrap *aAccWrap):
00060     MaiInterface(aAccWrap)
00061 {
00062 }
00063 
00064 MaiInterfaceAction::~MaiInterfaceAction()
00065 {
00066 }
00067 
00068 MaiInterfaceType
00069 MaiInterfaceAction::GetType()
00070 {
00071     return MAI_INTERFACE_ACTION;
00072 }
00073 
00074 const GInterfaceInfo *
00075 MaiInterfaceAction::GetInterfaceInfo()
00076 {
00077     static const GInterfaceInfo atk_if_action_info = {
00078         (GInterfaceInitFunc)interfaceInitCB,
00079         (GInterfaceFinalizeFunc) NULL,
00080         NULL
00081     };
00082     return &atk_if_action_info;
00083 }
00084 
00085 /* static functions */
00086 
00087 void
00088 interfaceInitCB(AtkActionIface *aIface)
00089 {
00090     NS_ASSERTION(aIface, "Invalid aIface");
00091     if (!aIface)
00092         return;
00093 
00094     aIface->do_action = doActionCB;
00095     aIface->get_n_actions = getActionCountCB;
00096     aIface->get_description = getDescriptionCB;
00097     aIface->get_keybinding = getKeyBindingCB;
00098     aIface->get_name = getNameCB;
00099     aIface->set_description = setDescriptionCB;
00100 }
00101 
00102 gboolean
00103 doActionCB(AtkAction *aAction, gint aActionIndex)
00104 {
00105     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
00106     NS_ENSURE_TRUE(accWrap, FALSE);
00107  
00108     nsresult rv = accWrap->DoAction(aActionIndex);
00109     return (NS_FAILED(rv)) ? FALSE : TRUE;
00110 }
00111 
00112 gint
00113 getActionCountCB(AtkAction *aAction)
00114 {
00115     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
00116     NS_ENSURE_TRUE(accWrap, 0);
00117 
00118     PRUint8 num = 0;
00119     nsresult rv = accWrap->GetNumActions(&num);
00120     return (NS_FAILED(rv)) ? 0 : NS_STATIC_CAST(gint, num);
00121 }
00122 
00123 const gchar *
00124 getDescriptionCB(AtkAction *aAction, gint aActionIndex)
00125 {
00126     // the interface in nsIAccessibleAction is empty
00127     // use getName as default description
00128     return getNameCB(aAction, aActionIndex);
00129 }
00130 
00131 const gchar *
00132 getNameCB(AtkAction *aAction, gint aActionIndex)
00133 {
00134     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
00135     NS_ENSURE_TRUE(accWrap, nsnull);
00136 
00137     MaiInterfaceAction *action =
00138         NS_STATIC_CAST(MaiInterfaceAction *,
00139                        accWrap->GetMaiInterface(MAI_INTERFACE_ACTION));
00140     NS_ENSURE_TRUE(action, nsnull);
00141 
00142     nsAutoString autoStr;
00143     nsresult rv = accWrap->GetActionName(aActionIndex, autoStr);
00144     NS_ENSURE_SUCCESS(rv, nsnull);
00145     action->SetName(autoStr);
00146     return action->GetName();
00147 }
00148 
00149 const gchar *
00150 getKeyBindingCB(AtkAction *aAction, gint aActionIndex)
00151 {
00152     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
00153     NS_ENSURE_TRUE(accWrap, nsnull);
00154 
00155     MaiInterfaceAction *action =
00156         NS_STATIC_CAST(MaiInterfaceAction *,
00157                        accWrap->GetMaiInterface(MAI_INTERFACE_ACTION));
00158     NS_ENSURE_TRUE(action, nsnull);
00159 
00160     if (*action->GetKeyBinding())
00161         return action->GetKeyBinding();
00162 
00163     //return all KeyBindings including accesskey and shortcut
00164     
00165     nsAutoString allKeyBinding;
00166 
00167     //get accesskey
00168     nsAutoString accessKey;
00169     nsresult rv = accWrap->GetKeyboardShortcut(accessKey);
00170 
00171     if (NS_SUCCEEDED(rv) && !accessKey.IsEmpty()) {
00172         nsCOMPtr<nsIAccessible> parentAccessible;
00173         accWrap->GetParent(getter_AddRefs(parentAccessible));
00174         if (parentAccessible) {
00175             PRUint32 role;
00176             parentAccessible->GetRole(&role);
00177 
00178             if (role == ATK_ROLE_MENU_BAR) {
00179                 //it is topmenu, change from "Alt+f" to "f;<Alt>f"
00180                 nsAutoString rightChar;
00181                 accessKey.Right(rightChar, 1);
00182                 allKeyBinding = rightChar + NS_LITERAL_STRING(";<Alt>") +
00183                                 rightChar;
00184             }
00185             else if ((role == ATK_ROLE_MENU) || (role == ATK_ROLE_MENU_ITEM)) {
00186                 //it is submenu, change from "s" to "s;<Alt>f:s"
00187                 nsAutoString allKey = accessKey;
00188                 nsCOMPtr<nsIAccessible> grandParentAcc = parentAccessible;
00189 
00190                 while ((grandParentAcc) && (role != ATK_ROLE_MENU_BAR)) {
00191                     nsAutoString grandParentKey;
00192                     grandParentAcc->GetKeyboardShortcut(grandParentKey);
00193 
00194                     if (!grandParentKey.IsEmpty()) {
00195                         nsAutoString rightChar;
00196                         grandParentKey.Right(rightChar, 1);
00197                         allKey = rightChar + NS_LITERAL_STRING(":") + allKey;
00198                     }
00199 
00200                     nsCOMPtr<nsIAccessible> tempAcc = grandParentAcc;
00201                     tempAcc->GetParent(getter_AddRefs(grandParentAcc));
00202                     if (grandParentAcc)
00203                         grandParentAcc->GetRole(&role);
00204                 }
00205                 allKeyBinding = accessKey + NS_LITERAL_STRING(";<Alt>") +
00206                                 allKey;
00207             }
00208         }
00209         else {
00210             //default process, rarely happens.
00211             nsAutoString rightChar;
00212             accessKey.Right(rightChar, 1);
00213             allKeyBinding = rightChar + NS_LITERAL_STRING(";<Alt>") + rightChar;
00214         }
00215     }
00216     else  //don't have accesskey
00217         allKeyBinding.AssignLiteral(";");
00218 
00219     //get shortcut
00220     nsAutoString keyBinding, subShortcut;
00221     rv = accWrap->GetKeyBinding(keyBinding);
00222 
00223     if (NS_SUCCEEDED(rv) && !keyBinding.IsEmpty()) {
00224         //change the shortcut from "Ctrl+Shift+L" to "<Control><Shift>L"
00225         PRInt32 oldPos, curPos=0;
00226         while ((curPos != -1) && (curPos < (PRInt32)keyBinding.Length())) {
00227             oldPos = curPos;
00228             nsAutoString subString;
00229             curPos = keyBinding.FindChar('+', oldPos);
00230             if (curPos == -1) {
00231                 keyBinding.Mid(subString, oldPos, keyBinding.Length() - oldPos);
00232                 subShortcut += subString;
00233             }
00234             else {
00235                 keyBinding.Mid(subString, oldPos, curPos - oldPos);
00236       
00237                 //change "Ctrl" to "Control"
00238                 if (subString.LowerCaseEqualsLiteral("ctrl"))
00239                     subString.AssignLiteral("Control");
00240       
00241                 subShortcut += NS_LITERAL_STRING("<") + subString +
00242                                NS_LITERAL_STRING(">");
00243                 curPos++;
00244             }
00245         }
00246     }
00247 
00248     allKeyBinding += NS_LITERAL_STRING(";") + subShortcut;
00249     action->SetKeyBinding(allKeyBinding);
00250     return action->GetKeyBinding();
00251 }
00252 
00253 gboolean
00254 setDescriptionCB(AtkAction *aAction, gint aActionIndex,
00255                  const gchar *aDesc)
00256 {
00257     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
00258     NS_ENSURE_TRUE(accWrap, nsnull);
00259 
00260     /* this is not supported in nsIAccessible yet */
00261     return FALSE;
00262 }