Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.options.keymap;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.netbeans.core.options.keymap.api.ShortcutAction;
import org.netbeans.core.options.keymap.spi.KeymapManager;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
/**
* There are 3 areas of information loaded using SPI:
*
*
profile definitions: set of profiles + current profile
*
actions: all actions registered in the system for keymap configuration
*
keymaps: the actual keymaps (action-keystroke) for individual profiles
*
* Out of those 3, actions loading takes most of the time, as action instances
* must be created. At least action initialization should NOT happen in the
* awt thread.
*
* Each of these areas area loaded by a "loader" (AL, KL, PL), which does all the processing
* and keeps the loaded data. In the case of multiple initial requests, the loading may
* happen multiple times, but only one loader will win and register itself in the member
* variable. The code was originally written to run in a RP, but more simple synchronization
* was chosen.
*
* Note: the class actually does not hold any own data; all data it serves are collected from
* KeymapManager instances, and change/deleteProfile will immediately write the changes to those
* Managers. So it's not necessary to keep multiple instances of KeymapModel - it only takes
* initialization time. Therefore {@link KeymapModel#create} should be used preferrably to constructor,
* so multiple instances in the future are supported.
*
* @author Jan Jancura, Svata Dedic
*/
public class KeymapModel {
/* package */ static final RequestProcessor RP = new RequestProcessor(KeymapModel.class);
private static final Logger LOG = Logger.getLogger(KeymapModel.class.getName ());
private static final Logger UI_LOG = Logger.getLogger("org.netbeans.ui.options"); // NOI18N
private static volatile List managers = null;
private static volatile KeymapModel INSTANCE;
static KeymapModel create() {
if (INSTANCE != null) {
return INSTANCE;
}
synchronized (KeymapModel.class) {
return INSTANCE = new KeymapModel();
}
}
/**
* @return All the registered implementations.
*/
public static Collection extends KeymapManager> getKeymapManagerInstances() {
if (managers != null) {
return managers;
}
final Lookup.Result r = Lookup.getDefault().lookupResult(KeymapManager.class);
ArrayList al = new ArrayList(r.allInstances());
al.trimToSize();
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("Dumping registered KeymapManagers: ");
for (KeymapManager m : al) {
LOG.fine(" KeymapManager: " + s2s(m));
}
LOG.fine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}
synchronized (KeymapModel.class) {
if (managers == null) {
managers = al;
r.addLookupListener(new LookupListener() {
@Override
public void resultChanged(LookupEvent ev) {
synchronized (KeymapModel.class) {
managers = null;
r.removeLookupListener(this);
}
if (INSTANCE != null) {
INSTANCE.refreshActions();
}
}
});
}
}
return al;
}
// actions .................................................................
public Set getActionCategories () {
AL data = ensureActionsLoaded();
return data.categories;
}
/**
* Data for set of all actions
*/
private volatile AL actionData;
/**
* Data for keymap profiles
*/
private volatile PL profileData;
/**
* The keymaps themselves
*/
private volatile KL keymapData;
/**
* Loads and processes action data from the underlying KeymapManagers
*/
private class AL implements Runnable {
private volatile AL current;
private Set categories;
private Set allActionIds = new HashSet();
private Set duplicateIds = new HashSet();
private Map> categoryToActions =
new HashMap>();
private Map sharedActions =
new HashMap();
public void run() {
if ((current = actionData) != null) {
return;
}
List