This commit is contained in:
huangyuhui 2017-02-22 20:12:21 +08:00
parent f4d148b042
commit d1c4dee7f7
303 changed files with 15121 additions and 2180 deletions

View File

@ -4,6 +4,8 @@ jdk:
branches:
only:
- master
before_install:
- chmod +x gradlew
before_deploy:
- git config --global user.email ${GITHUB_EMAIL}
- git config --global user.name ${GITHUB_NAME}
@ -14,8 +16,7 @@ deploy:
provider: releases
api_key:
secure: KxGIpE83MsgSdWNwCyqgIKJevZgLAef3hpBEVZjqZ09mA3JjQzWCbVFEfWpv8yRqe8ue7YF0aH7YoWuqOiE9q93Qsvv3GRtVcnZqZiGZbCZer1ShtqcjSseMvsw66dtHNcdK6onHna+OrCh2TQjxE2tKMf3CPCP9K2RI6dYOTyYUWmiOmiYQfcd2MEGSRXdnCGi8nf5oBZOYfHforRH3QYJXA7AxI+I9xaEWimFKs1c73sE1pypIGw5rlc+tiKuG8f5QoMeEOy+D30Qe3Vlre13RTi73r6GVt1ZoRpAwlNLEgjD393V1mxGd9wYNBMRKIZ/dfvIAN4m/jltVpgSyuCiUj3sjNs39HV8Jk0ki6RoSoAsjIyWHWfag946sk5wuBjnIZajlQhpGoc94ml8ujxOqP0npQT8azm3CwkAmBx0cxQ09Td9WPREk9BL4bWZrp5t50PsB9SZHPV2ET98QQH6+ArldONYWDTNZMJ2Lc0s6rFZoInq2px1srbR7Cxq2rNsVRp15UFvQp5xueONXz68/wFet6Gbm2ob8TGKm1bQOh5MRO/fq+fkrIIjoD6ztlRaO3xtePXlyEbnJmyxXOdA+Rd9WFXsT9gzjKtlxQjdHZNnI0YiEjR2qvHIWguAQtuV4pydWi8VtlBQ2gT37CpF4ApfC6jTfMsEwqZZ29YM=
file:
- HMCL/build/libs
file: HMCL/build/libs
on:
repo: huanghongxun/HMCL
script: "bash ./gradlew clean build --stacktrace"

View File

@ -41,7 +41,7 @@ if (buildnumber == null)
def versionroot = System.getenv("VERSION_ROOT")
if (versionroot == null)
versionroot = "2.7.3"
versionroot = "2.7.4"
String mavenGroupId = 'HMCL'
String mavenVersion = versionroot + '.' + buildnumber

View File

@ -24,7 +24,6 @@ import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -34,14 +33,11 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
import javax.swing.ImageIcon;
import javax.swing.RepaintManager;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.api.ILogger;
import org.jackhuang.hmcl.api.PluginManager;
import org.jackhuang.hmcl.api.VersionNumber;
import org.jackhuang.hmcl.laf.HelloMinecraftLookAndFeel;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.ui.LogWindow;
import org.jackhuang.hmcl.ui.MainFrame;
@ -57,6 +53,7 @@ import org.jackhuang.hmcl.util.log.layout.DefaultLayout;
import org.jackhuang.hmcl.util.sys.ProcessManager;
import org.jackhuang.hmcl.util.ui.MyRepaintManager;
import org.jackhuang.hmcl.util.upgrade.IUpgrader;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
/**
*
@ -97,7 +94,7 @@ public final class Main implements Runnable {
return "HMCL" + ' ' + LAUNCHER_VERSION;
}
private static HelloMinecraftLookAndFeel LOOK_AND_FEEL;
//private static HelloMinecraftLookAndFeel LOOK_AND_FEEL;
private static final Logger LOGGER = Logger.getLogger(Main.class.getName());
@ -190,10 +187,9 @@ public final class Main implements Runnable {
MessageBox.showLocalized("ui.message.open_jdk");
try {
LOOK_AND_FEEL = new HelloMinecraftLookAndFeel(Settings.getInstance().getTheme().settings);
UIManager.setLookAndFeel(LOOK_AND_FEEL);
BeautyEyeLNFHelper.launchBeautyEyeLNF();
RepaintManager.setCurrentManager(new MyRepaintManager());
} catch (ParseException | UnsupportedLookAndFeelException ex) {
} catch (Exception ex) {
HMCLog.warn("Failed to set look and feel...", ex);
}

View File

@ -58,7 +58,7 @@
<Component class="javax.swing.JTable" name="lstDownloads">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="SwingUtils.makeDefaultTableModel(new String[]{C.i18n(&quot;install.version&quot;), C.i18n(&quot;install.time&quot;), C.i18n(&quot;install.type&quot;)},new Class[]{String.class, String.class, String.class}, new boolean[]{false, false, false})" type="code"/>
<Connection code="SwingUtils.makeDefaultTableModel(new String[]{C.i18n(&quot;install.version&quot;), C.i18n(&quot;install.release_time&quot;), C.i18n(&quot;install.time&quot;), C.i18n(&quot;install.type&quot;)},new Class[]{String.class, String.class, String.class, String.class}, new boolean[]{false, false, false, false})" type="code"/>
</Property>
<Property name="toolTipText" type="java.lang.String" value=""/>
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">

View File

@ -19,6 +19,7 @@ package org.jackhuang.hmcl.ui;
import org.jackhuang.hmcl.util.ui.Page;
import javax.swing.table.DefaultTableModel;
import org.jackhuang.hmcl.api.ui.TopTabPage;
import org.jackhuang.hmcl.core.download.MinecraftRemoteVersions;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.util.C;
@ -64,7 +65,7 @@ public class GameDownloadPanel extends Page {
}
});
lstDownloads.setModel(SwingUtils.makeDefaultTableModel(new String[]{C.i18n("install.version"), C.i18n("install.time"), C.i18n("install.type")},new Class[]{String.class, String.class, String.class}, new boolean[]{false, false, false}));
lstDownloads.setModel(SwingUtils.makeDefaultTableModel(new String[]{C.i18n("install.version"), C.i18n("install.release_time"), C.i18n("install.time"), C.i18n("install.type")},new Class[]{String.class, String.class, String.class, String.class}, new boolean[]{false, false, false, false}));
lstDownloads.setToolTipText("");
lstDownloads.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
jScrollPane2.setViewportView(lstDownloads);
@ -110,7 +111,7 @@ public class GameDownloadPanel extends Page {
DefaultTableModel model = SwingUtils.clearDefaultTable(lstDownloads);
model.addRow(new Object[] { C.i18n("message.loading"), "", "" });
MinecraftRemoteVersions.refreshRomoteVersions(Settings.getLastProfile().service().getDownloadType())
.reg((ver) -> model.addRow(new Object[] { ver.id, ver.time,
.reg((ver) -> model.addRow(new Object[] { ver.id, ver.releaseTime, ver.time,
StrUtils.equalsOne(ver.type, "old_beta", "old_alpha", "release", "snapshot") ? C.i18n("versions." + ver.type) : ver.type }))
.regDone(SwingUtils.invokeLater(() -> {
lstDownloads.requestFocus();
@ -138,8 +139,8 @@ public class GameDownloadPanel extends Page {
boolean refreshedDownloads = false;
@Override
public void onSelect() {
super.onSelect();
public void onSelect(TopTabPage page) {
super.onSelect(page);
if (!refreshedDownloads) {
refreshedDownloads = true;
refreshDownloads();

View File

@ -26,7 +26,7 @@
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="tabVersionEdit" alignment="1" max="32767" attributes="0"/>
<Component id="tabVersionEdit" alignment="1" pref="766" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="btnMakeLaunchScript" min="-2" max="-2" attributes="0"/>
@ -42,7 +42,7 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="btnIncludeMinecraft" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="577" max="32767" attributes="0"/>
<EmptySpace pref="677" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
@ -50,7 +50,7 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="pnlTop" min="-2" max="-2" attributes="0"/>
<Component id="pnlTop" min="-2" pref="70" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="tabVersionEdit" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
@ -63,7 +63,7 @@
</Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace pref="400" max="32767" attributes="0"/>
<EmptySpace pref="403" max="32767" attributes="0"/>
<Component id="btnIncludeMinecraft" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -119,7 +119,7 @@
<Component id="lblDimensionX" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtHeight" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace pref="88" max="32767" attributes="0"/>
<EmptySpace pref="182" max="32767" attributes="0"/>
<Component id="chkFullscreen" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
@ -194,7 +194,7 @@
<Component id="lblDimension" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtWidth" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="39" max="32767" attributes="0"/>
<EmptySpace pref="51" max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnDownloadAllAssets" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnCleanGame" alignment="3" min="-2" max="-2" attributes="0"/>
@ -408,7 +408,7 @@
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="txtJavaArgs" pref="325" max="32767" attributes="0"/>
<Component id="txtJavaArgs" pref="457" max="32767" attributes="0"/>
<Component id="txtMinecraftArgs" max="32767" attributes="0"/>
<Component id="txtPermSize" alignment="1" max="32767" attributes="0"/>
</Group>
@ -421,7 +421,7 @@
<Component id="chkNoJVMArgs" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="chkNoCommon" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="96" max="32767" attributes="0"/>
<EmptySpace pref="190" max="32767" attributes="0"/>
<Component id="chkDontCheckGame" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
@ -627,7 +627,7 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="jScrollPane1" pref="550" max="32767" attributes="0"/>
<Component id="jScrollPane1" pref="644" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="btnRemoveMod" max="32767" attributes="0"/>
@ -635,7 +635,7 @@
</Group>
</Group>
<Group type="102" alignment="1" attributes="0">
<Component id="lblModInfo" pref="646" max="32767" attributes="0"/>
<Component id="lblModInfo" pref="751" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
@ -650,7 +650,7 @@
<Component id="btnRemoveMod" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="jScrollPane1" pref="259" max="32767" attributes="0"/>
<Component id="jScrollPane1" pref="271" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="lblModInfo" min="-2" max="-2" attributes="0"/>
@ -723,6 +723,9 @@
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="pnlAutoInstall">
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new Page()"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="&lt;settings.tabs.installers&gt;">

View File

@ -322,7 +322,7 @@ public final class GameSettingsPanel extends RepaintPage implements DropTargetLi
btnAddMod = new javax.swing.JButton();
btnRemoveMod = new javax.swing.JButton();
lblModInfo = new javax.swing.JLabel();
pnlAutoInstall = new javax.swing.JPanel();
pnlAutoInstall = new Page();
tabInstallers = new NewTabPane();
pnlTop = new javax.swing.JPanel();
pnlSelection = new javax.swing.JPanel();
@ -479,7 +479,7 @@ public final class GameSettingsPanel extends RepaintPage implements DropTargetLi
.addComponent(lblDimensionX)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtHeight, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 88, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 182, Short.MAX_VALUE)
.addComponent(chkFullscreen))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlSettingsLayout.createSequentialGroup()
.addComponent(txtMaxMemory)
@ -539,7 +539,7 @@ public final class GameSettingsPanel extends RepaintPage implements DropTargetLi
.addComponent(lblDimensionX, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblDimension)
.addComponent(txtWidth, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 39, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 51, Short.MAX_VALUE)
.addGroup(pnlSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnDownloadAllAssets)
.addComponent(btnCleanGame))
@ -632,7 +632,7 @@ public final class GameSettingsPanel extends RepaintPage implements DropTargetLi
.addComponent(lblJavaArgs))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlAdvancedSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(txtJavaArgs, javax.swing.GroupLayout.DEFAULT_SIZE, 325, Short.MAX_VALUE)
.addComponent(txtJavaArgs, javax.swing.GroupLayout.DEFAULT_SIZE, 457, Short.MAX_VALUE)
.addComponent(txtMinecraftArgs)
.addComponent(txtPermSize, javax.swing.GroupLayout.Alignment.TRAILING)))
.addGroup(pnlAdvancedSettingsLayout.createSequentialGroup()
@ -643,7 +643,7 @@ public final class GameSettingsPanel extends RepaintPage implements DropTargetLi
.addComponent(chkNoJVMArgs)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkNoCommon)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 96, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 190, Short.MAX_VALUE)
.addComponent(chkDontCheckGame))
.addGroup(pnlAdvancedSettingsLayout.createSequentialGroup()
.addGroup(pnlAdvancedSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -728,13 +728,13 @@ public final class GameSettingsPanel extends RepaintPage implements DropTargetLi
pnlModManagementContentLayout.setHorizontalGroup(
pnlModManagementContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlModManagementContentLayout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 550, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 644, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlModManagementContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(btnRemoveMod, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnAddMod, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlModManagementContentLayout.createSequentialGroup()
.addComponent(lblModInfo, javax.swing.GroupLayout.DEFAULT_SIZE, 646, Short.MAX_VALUE)
.addComponent(lblModInfo, javax.swing.GroupLayout.DEFAULT_SIZE, 751, Short.MAX_VALUE)
.addContainerGap())
);
pnlModManagementContentLayout.setVerticalGroup(
@ -746,7 +746,7 @@ public final class GameSettingsPanel extends RepaintPage implements DropTargetLi
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnRemoveMod)
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 259, Short.MAX_VALUE))
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 271, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblModInfo))
);
@ -950,7 +950,7 @@ public final class GameSettingsPanel extends RepaintPage implements DropTargetLi
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tabVersionEdit, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(tabVersionEdit, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 766, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(btnMakeLaunchScript)
@ -963,12 +963,12 @@ public final class GameSettingsPanel extends RepaintPage implements DropTargetLi
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(btnIncludeMinecraft)
.addContainerGap(577, Short.MAX_VALUE)))
.addContainerGap(677, Short.MAX_VALUE)))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(pnlTop, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pnlTop, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(tabVersionEdit)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@ -979,7 +979,7 @@ public final class GameSettingsPanel extends RepaintPage implements DropTargetLi
.addContainerGap())
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(400, Short.MAX_VALUE)
.addContainerGap(403, Short.MAX_VALUE)
.addComponent(btnIncludeMinecraft)
.addContainerGap()))
);

View File

@ -21,6 +21,7 @@ import org.jackhuang.hmcl.util.ui.Page;
import java.util.List;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import org.jackhuang.hmcl.api.ui.TopTabPage;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.core.install.InstallerType;
@ -164,7 +165,8 @@ public class InstallerPanel extends Page {
boolean refreshed = false;
@Override
public void onSelect() {
public void onSelect(TopTabPage page) {
super.onSelect(page);
if (!refreshed) {
TaskWindow.factory().execute(refreshVersionsTask());
refreshed = true;

View File

@ -37,6 +37,7 @@ import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.util.MessageBox;
import org.jackhuang.hmcl.api.func.Consumer;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.util.DefaultPlugin;
import org.jackhuang.hmcl.util.sys.FileUtils;
import org.jackhuang.hmcl.util.sys.ProcessMonitor;
import org.jackhuang.hmcl.util.net.WebFrame;
@ -111,6 +112,7 @@ public class LaunchingUIDaemon {
void runGame(Profile profile) {
MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching"));
profile.launcher().genLaunchCode(value -> {
DefaultPlugin.INSTANCE.saveAuthenticatorConfig();
((HMCLGameLauncher.GameLauncherTag) value.getTag()).state = 1;
}, MainFrame.INSTANCE::failed, Settings.getInstance().getAuthenticator().getPassword());
}
@ -118,6 +120,7 @@ public class LaunchingUIDaemon {
void makeLaunchScript(Profile profile) {
MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching"));
profile.launcher().genLaunchCode(value -> {
DefaultPlugin.INSTANCE.saveAuthenticatorConfig();
((HMCLGameLauncher.GameLauncherTag) value.getTag()).state = 2;
}, MainFrame.INSTANCE::failed, Settings.getInstance().getAuthenticator().getPassword());
}
@ -154,9 +157,8 @@ public class LaunchingUIDaemon {
if (v != LauncherVisibility.KEEP && !LogWindow.INSTANCE.isVisible()) {
HMCLog.log("Launcher will exit now.");
System.exit(0);
} else {
} else
HMCLog.log("Launcher will not exit now.");
}
}
private static final Consumer<LaunchSucceededEvent> LAUNCH_SCRIPT_FINISHER = event -> {

View File

@ -40,6 +40,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
@ -49,6 +50,7 @@ import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.Main;
import org.jackhuang.hmcl.api.PluginManager;
@ -165,7 +167,6 @@ public final class MainFrame extends DraggableFrame implements IRepaint {
private void initComponents() {
setLayout(null);
initBorderColor(Settings.getInstance().getTheme());
realPanel = new JPanel();
realPanel.setLayout(null);
@ -255,6 +256,8 @@ public final class MainFrame extends DraggableFrame implements IRepaint {
realPanel.setBounds(1, 0, 800, 511);
add(realPanel);
reloadColor(Settings.getInstance().getTheme());
}
private transient final ActionListener tabListener = e -> MainFrame.this.selectTab(e.getActionCommand());
@ -277,11 +280,12 @@ public final class MainFrame extends DraggableFrame implements IRepaint {
public void selectTab(String tabName) {
int chosen = -1;
TopTabPage onCreate = null, onSelect = null;
TopTabPage onCreate = null, onSelect = null, lastPage = null;
for (int i = 0; i < tabHeader.size(); i++)
if (tabName.equalsIgnoreCase(tabHeader.get(i).getActionCommand())) {
if (!tabContent.get(i).isCreated()) {
onCreate = tabContent.get(i);
onCreate.setId(i);
tabWrapper[i].add(tabContent.get(i));
} else if (tabContent.get(i).isSelected())
continue;
@ -290,8 +294,10 @@ public final class MainFrame extends DraggableFrame implements IRepaint {
}
if (chosen != -1) {
for (int i = 0; i < tabHeader.size(); i++)
if (i != chosen && tabContent.get(i) != null && tabContent.get(i).isSelected())
tabContent.get(i).onLeave();
if (i != chosen && tabContent.get(i) != null && tabContent.get(i).isSelected()) {
lastPage = tabContent.get(i);
lastPage.onLeave();
}
for (int i = 0; i < tabHeader.size(); i++)
if (i == chosen) {
for (int j = 0; j < tabHeader.size(); j++)
@ -305,7 +311,7 @@ public final class MainFrame extends DraggableFrame implements IRepaint {
if (onCreate != null)
onCreate.onCreate();
if (onSelect != null)
onSelect.onSelect();
onSelect.onSelect(lastPage);
}
}
@ -382,13 +388,18 @@ public final class MainFrame extends DraggableFrame implements IRepaint {
Color borderColor;
Color borderColorDarker;
private void initBorderColor(Theme t) {
borderColor = GraphicsUtils.getWebColor(t.settings.get("Customized.MainFrame.background"));
borderColorDarker = GraphicsUtils.getWebColor(t.settings.get("Customized.MainFrame.selected_background"));
private void initBorderColor() {
borderColor = UIManager.getColor("Customized.MainFrame.background");
borderColorDarker = UIManager.getColor("Customized.MainFrame.selected_background");
}
public void reloadColor(Theme t) {
initBorderColor(t);
for (Map.Entry<String, String> entry : t.settings.entrySet()) {
if (entry.getValue().startsWith("#"))
UIManager.put(entry.getKey(), GraphicsUtils.getWebColor(entry.getValue()));
}
initBorderColor();
if (border != null)
border.setColor(borderColor);
header.setBackground(borderColor);

View File

@ -45,7 +45,7 @@ import org.jackhuang.hmcl.core.version.MinecraftVersion;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.core.mod.ModpackManager;
import org.jackhuang.hmcl.ui.modpack.ModpackWizard;
import org.jackhuang.hmcl.laf.ConstomButton;
import org.jackhuang.hmcl.laf.button.CustomButton;
import org.jackhuang.hmcl.api.func.Consumer;
import org.jackhuang.hmcl.util.sys.FileUtils;
import org.jackhuang.hmcl.util.task.TaskWindow;
@ -54,6 +54,7 @@ import org.jackhuang.hmcl.util.ui.JSystemFileChooser;
import org.jackhuang.hmcl.util.ui.SwingUtils;
import org.jackhuang.hmcl.util.ui.wizard.api.WizardDisplayer;
import org.jackhuang.hmcl.api.auth.IAuthenticator;
import org.jackhuang.hmcl.laf.button.CustomButtonUI;
/**
*
@ -67,13 +68,11 @@ public class MainPagePanel extends Page {
void initGui() {
initComponents();
animationEnabled = false;
pnlButtons = new javax.swing.JPanel();
pnlButtons.setLayout(null);
int w = 150, h = 50;
btnRun = new ConstomButton();
btnRun = new CustomButton();
btnRun.setBounds(0, 0, w, h);
Font font = btnRun.getFont();
Font newFont = new Font(font.getName(), font.getStyle(), 15);
@ -82,6 +81,7 @@ public class MainPagePanel extends Page {
btnRun.setText(C.i18n("ui.button.run"));
btnRun.setFont(newFont);
btnRun.addActionListener(e -> MainFrame.INSTANCE.daemon.runGame(Settings.getLastProfile()));
btnRun.setUI(new CustomButtonUI());
pnlRoot.add(pnlButtons);
pnlButtons.setBounds(0, 0, w, h);
@ -434,7 +434,7 @@ public class MainPagePanel extends Page {
boolean preparingAuth = true;
private boolean isLoading = false;
private javax.swing.JPanel pnlButtons;
private ConstomButton btnRun;
private CustomButton btnRun;
private static final int DEFAULT_WIDTH = 800, DEFAULT_HEIGHT = 480;
//</editor-fold>

View File

@ -40,10 +40,20 @@ public class NewTabPane extends JTabbedPane implements ChangeListener {
if (initializing)
return;
for (int i = 0; i < getComponentCount(); ++i)
if (getSelectedIndex() != i && getComponent(i) instanceof TopTabPage)
((TopTabPage) getComponent(i)).onLeave();
if (getSelectedComponent() instanceof TopTabPage)
((TopTabPage) getSelectedComponent()).onSelect();
if (getComponent(i) instanceof TopTabPage) {
TopTabPage comp = (TopTabPage) getComponent(i);
comp.setId(i);
if (getSelectedIndex() != i)
((TopTabPage) getComponent(i)).onLeave();
}
if (getSelectedComponent() instanceof TopTabPage) {
if (page == null && getComponentCount() > 0 && getComponent(0) instanceof TopTabPage)
page = (TopTabPage) getComponent(0);
((TopTabPage) getSelectedComponent()).onSelect(page);
page = (TopTabPage) getSelectedComponent();
}
}
TopTabPage page = null;
}

View File

@ -37,8 +37,10 @@ import org.jackhuang.hmcl.laf.LAFTheme;
* @author huangyuhui
*/
public class DefaultPlugin implements IPlugin {
public static DefaultPlugin INSTANCE;
public DefaultPlugin() {
INSTANCE = this;
for (Theme t : LAFTheme.THEMES)
Theme.THEMES.put(t.getId(), t);
}
@ -52,11 +54,8 @@ public class DefaultPlugin implements IPlugin {
auths.add(new YggdrasilAuthenticator(clientToken));
try {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
for (IAuthenticator i : auths)
Settings.getInstance().setAuthenticatorConfig(i.id(), i.onSaveSettings());
}));
} catch(IllegalStateException ignore) { // Shutdown in progress
Runtime.getRuntime().addShutdownHook(new Thread(this::saveAuthenticatorConfig));
} catch (IllegalStateException ignore) { // Shutdown in progress
}
for (IAuthenticator i : auths) {
i.onLoadSettings(Settings.getInstance().getAuthenticatorConfig(i.id()));
@ -64,6 +63,11 @@ public class DefaultPlugin implements IPlugin {
}
}
public void saveAuthenticatorConfig() {
for (IAuthenticator i : auths)
Settings.getInstance().setAuthenticatorConfig(i.id(), i.onSaveSettings());
}
@Override
public void onAddTab(JFrame frame, AddTabCallback callback) {
callback.addTab(new MainPagePanel(), "main", C.i18n("launcher.title.main"));

View File

@ -29,9 +29,13 @@ public abstract class TopTabPage extends JPanel {
public abstract boolean isCreated();
public abstract void onSelect();
public abstract void onSelect(TopTabPage lastSelectedPage);
public abstract boolean isSelected();
public abstract void onLeave();
public abstract int getId();
public abstract void setId(int id);
}

View File

@ -17,15 +17,10 @@
*/
package org.jackhuang.hmcl.util.sys;
import com.sun.management.OperatingSystemMXBean;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.util.Locale;
import java.util.StringTokenizer;
import org.jackhuang.hmcl.util.code.Charsets;
import org.jackhuang.hmcl.api.HMCLog;
/**
@ -68,56 +63,20 @@ public enum OS {
*/
public static long getTotalPhysicalMemory() {
try {
if (os() == LINUX)
return memoryInfoForLinux()[0] * 1024;
else {
OperatingSystemMXBean o = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
return o.getTotalPhysicalMemorySize();
}
return ReflectionHelper.get(ManagementFactory.getOperatingSystemMXBean(), "getTotalPhysicalMemorySize");
} catch (Throwable t) {
HMCLog.warn("Failed to get total physical memory size", t);
return -1;
return 1024;
}
}
public static int getSuggestedMemorySize() {
long total = getTotalPhysicalMemory();
if (total == -1)
return 1024;
int memory = (int) (total / 1024 / 1024) / 4;
memory = Math.round((float) memory / 128.0f) * 128;
return memory;
}
public static long[] memoryInfoForLinux() throws IOException {
File file = new File("/proc/meminfo");
try (BufferedReader br = new BufferedReader(new InputStreamReader(FileUtils.openInputStream(file), Charsets.UTF_8))) {
long[] result = new long[4];
String str;
StringTokenizer token;
while ((str = br.readLine()) != null) {
token = new StringTokenizer(str);
if (!token.hasMoreTokens())
continue;
str = token.nextToken();
if (!token.hasMoreTokens())
continue;
if (str.equalsIgnoreCase("MemTotal:"))
result[0] = Long.parseLong(token.nextToken());
else if (str.equalsIgnoreCase("MemFree:"))
result[1] = Long.parseLong(token.nextToken());
else if (str.equalsIgnoreCase("SwapTotal:"))
result[2] = Long.parseLong(token.nextToken());
else if (str.equalsIgnoreCase("SwapFree:"))
result[3] = Long.parseLong(token.nextToken());
}
return result;
}
}
public static String getLinuxReleaseVersion() throws IOException {
return FileUtils.read(new File("/etc/issue"));
}

View File

@ -34,7 +34,7 @@ import org.jackhuang.hmcl.api.IProcess;
public class ProcessThread extends Thread {
IProcess p;
public final EventHandler<SimpleEvent<String>> printlnEvent = new EventHandler<>();
public final EventHandler<SimpleEvent<IProcess>> stopEvent = new EventHandler<>();

View File

@ -0,0 +1,66 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util.sys;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import sun.misc.Unsafe;
/**
*
* @author huang
*/
public class ReflectionHelper {
private static Unsafe unsafe = null;
private static long objectFieldOffset;
static {
try {
unsafe = AccessController.doPrivileged(new PrivilegedExceptionAction<Unsafe> () {
@Override
public Unsafe run() throws Exception {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
return (Unsafe) theUnsafe.get(null);
}
});
Field overrideField = AccessibleObject.class.getDeclaredField("override");
objectFieldOffset = unsafe.objectFieldOffset(overrideField);
} catch (Throwable ex) {
}
}
private static void setAccessible(AccessibleObject obj) {
unsafe.putBoolean(obj, objectFieldOffset, true);
}
public static <T> T get(Object obj, String fieldName) {
try {
Method method = obj.getClass().getDeclaredMethod(fieldName);
setAccessible(method);
return (T) method.invoke(obj);
} catch (Throwable ex) {
return null;
}
}
}

View File

@ -32,6 +32,17 @@ import javax.swing.Timer;
public class Page extends TopTabPage {
boolean selected = false;
public int id;
@Override
public int getId() {
return id;
}
@Override
public void setId(int id) {
this.id = id;
}
@Override
public boolean isSelected() {
@ -39,9 +50,11 @@ public class Page extends TopTabPage {
}
@Override
public void onSelect() {
if (!selected)
public void onSelect(TopTabPage lastSelectedPage) {
if (!selected) {
lastPage = (Page) lastSelectedPage;
animate();
}
selected = true;
}
@ -65,13 +78,13 @@ public class Page extends TopTabPage {
// -------------------
// Animation
// -------------------
private static final int ANIMATION_LENGTH = 10;
private static final int ANIMATION_LENGTH = 5;
public Page() {
timer = new Timer(1, (e) -> {
SwingUtilities.invokeLater(() -> {
Page.this.repaint();
offsetX += 0.15;
offsetX += 0.14;
if (offsetX >= ANIMATION_LENGTH) {
timer.stop();
Page.this.repaint();
@ -80,7 +93,7 @@ public class Page extends TopTabPage {
});
}
BufferedImage cache = null;
BufferedImage cache = null, lastCache = null;
@Override
public void paint(Graphics g) {
@ -88,33 +101,50 @@ public class Page extends TopTabPage {
super.paint(g);
return;
}
double pgs = 1 - Math.sin(Math.PI / 2 / ANIMATION_LENGTH * offsetX);
Graphics2D gg = (Graphics2D) g;
double pgs = Math.sin(Math.PI / 2 / ANIMATION_LENGTH * offsetX);
if (Math.abs(ANIMATION_LENGTH - offsetX) < 0.1) {
super.paint(g);
return;
}
if (offsetX == 0) {
cache = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = cache.createGraphics();
if (isOpaque()) {
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
}
super.paint(g2d);
g2d.dispose();
cache = cacheImpl(this);
if (lastPage != null)
lastCache = cacheImpl(lastPage);
}
if (pgs > 1)
pgs = 1;
if (pgs < 0)
pgs = 0;
Graphics2D gg = (Graphics2D) g;
gg.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, (float) (1 - pgs)));
g.drawImage(cache, (int) (pgs * 50), 0, this);
int ori = lastPage != null ? (lastPage.getId() < getId() ? 1 : -1) : 1;
if (pgs >= 0.5)
animateImpl(gg, cache, (int) (((1 - (pgs - 0.5) * 2)) * totalOffset * ori), (float) ((pgs - 0.5) * 2));
else
animateImpl(gg, lastCache, (int) (((- pgs * 2)) * totalOffset * ori), (float) (1 - pgs * 2));
}
double offsetX = ANIMATION_LENGTH;
BufferedImage cacheImpl(Page page) {
BufferedImage image = new BufferedImage(page.getWidth(), page.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = image.createGraphics();
if (isOpaque()) {
g2d.setColor(page.getBackground());
g2d.fillRect(0, 0, page.getWidth(), page.getHeight());
}
page.superPaint(g2d);
g2d.dispose();
return image;
}
void animateImpl(Graphics2D g, BufferedImage image, int left, float alpha) {
if (image == null)
return;
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
g.drawImage(image, left, 0, this);
}
protected void superPaint(Graphics2D g) {
super.paint(g);
}
double offsetX = ANIMATION_LENGTH, totalOffset = 20;
Page lastPage;
Timer timer;
protected boolean animationEnabled = true;

View File

@ -0,0 +1,391 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BeautyEyeLNFHelper.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf;
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.border.Border;
import org.jackhuang.hmcl.laf.widget.border.BEShadowBorder;
import org.jackhuang.hmcl.laf.widget.border.BEShadowBorder3;
import org.jackhuang.hmcl.laf.widget.border.PlainGrayBorder;
/**
* <p>
* BeautyEye Swing外观实现方案 - L&F核心辅助类.<br>
* <p>
* 项目托管地址https://github.com/JackJiang2011/beautyeye
*
* @author Jack Jiang(jb2011@163.com), 2012-05
* @version 1.0
*/
public class BeautyEyeLNFHelper {
/**
* 开关量用于开启/关闭BeautyEye LNF的调试信息输出.
* <p>
* 默认false即不开启调试信息输出.
*
* @since 3.2
*/
public static boolean debug = false;
/**
* 开关量用于开启/关闭当窗口包括JFrameJDialog处于非活动 状态inactivity时的半透明视觉效果.
* <p>
* 默认true即表示默认开启半透明效果.
*
* @since 3.2
*/
public static boolean translucencyAtFrameInactive = true;
/**
* BeautyEye LNF 的窗口边框样式.
* <p>
* 默认值运行在java1.6.0_u10及以上版本时使用
* {@link FrameBorderStyle#translucencyAppleLike}
* 运行在java1.5版本时使用{@link FrameBorderStyle#generalNoTranslucencyShadow}.
*
* <p>
* <b>注意</b>如需设置本参数请确保它在UIManager.setLookAndFeel前被设置否则将不会起效哦.
*
* @see FrameBorderStyle
*/
public static FrameBorderStyle frameBorderStyle = FrameBorderStyle.translucencyAppleLike;
/**
* 颜色全局变量正常情况下的窗口文本颜色.
* <p>
* 你可设置本变量也可直接通过{@code UIManager.put("activeCaptionText",new ColorUIResource(c))}
* {@code UIManager.put("inactiveCaptionText",new ColorUIResource(c))}来实现窗口文本颜色的改变.
* <p>
* 窗体不活动(inactivite)时的颜色将据此自动计算出来无需额外设置. 默认是黑色new Color(0,0,0).
*/
public static Color activeCaptionTextColor = new Color(0, 0, 0);//黑色
/**
* 颜色全局变量多数组件的背景色.
* <p>
* 你可设置本变量也可直接通过各自的UIManager属性来改变它们.
* <p>
* 默认是浅灰色new Color(250,250,250).
*
* @since 3.2
*/
public static Color commonBackgroundColor = new Color(250, 250, 250);//240,240,240); //248,248,248);//255,255,255);//
/**
* 颜色全局变量多数组件的前景色文本颜色.
* <p>
* 你可设置本变量也可直接通过各自的UIManager属性来改变它们.
* <p>
* 默认是深灰色new Color(60,60,60).
*
* @since 3.2
*/
public static Color commonForegroundColor = new Color(60, 60, 60);//102,102,102);
/**
* 颜色全局变量某些组件的焦点边框颜色. 当前主要用于按钮等焦点边框的绘制颜色.
* <p>
* 你可设置本变量也可直接通过各自的UIManager属性来改变它们.
* <p>
* 默认是浅灰色new Color(250,250,250).
*
* @since 3.2
*/
public static Color commonFocusedBorderColor = new Color(162, 162, 162);
/**
* 颜色全局变量某些组件被禁用时的文本颜色. 当前主要用于菜单项中.
* <p>
* 你可设置本变量也可直接通过各自的UIManager属性来改变它们.
* <p>
* 默认是浅灰色new Color(172,168,153).
*
* @since 3.2
*/
public static Color commonDisabledForegroundColor = new Color(172, 168, 153);
/**
* 颜色全局变量多数组件中文本被选中时的背景色.当前主要用于各文本组件等.
* <p>
* 你可设置本变量也可直接通过各自的UIManager属性来改变它们.
* <p>
* 默认是深灰色new Color(2,129,216).
*
* @since 3.2
*/
public static Color commonSelectionBackgroundColor = new Color(2, 129, 216);//78,155,193));//58,135,173));//235,217,147));//new Color(255,237,167));
/**
* 颜色全局变量多数组件中文本被选中时的前景色文本颜色.当前主要用于各文本组件菜单项等.
* <p>
* 你可设置本变量也可直接通过各自的UIManager属性来改变它们.
* <p>
* 默认是深灰色new Color(255,255,255).
*
* @since 3.2
*/
public static Color commonSelectionForegroundColor = new Color(255, 255, 255);
/**
* 开关量用于默认设置或不设置窗口Frame及其子类的设置此窗体的最大化边界.
* <p>
* 此开关量是它是为了解决这样一个问题 <br>
* 当不使用操作系统的窗口装饰即使用完全自定义的窗口标题边框在windows上最 大化窗口时将会全屏显示从而覆盖了下方的任务栏task
* bar这个问题 据说自2002年 就已存在SUN一直未解决或者根本不认为是bug目前的解决方案是当本变量是true时则
* 默认为每一个窗体设置最大化边界否则保持系统默认不过这样设置并非完美方案一旦 设置了最大边界则此后无论Task Bar再怎么调
* 整大小比如被hide了则窗体永远是设 置时的最大边界不过目前也只能这么折中解决了因为窗体最大化事件处理并非L&F中实现
* 暂未找到其它更好的方法
* <p>
* 默认true即表示默认开启此设置.
*
* @since 3.2
* @see javax.swing.JFrame#setMaximizedBounds(java.awt.Rectangle)
*/
public static boolean setMaximizedBoundForFrame = true;
/**
* BeautyEye LNF的外观实现核心方法.
* <p>
* 本方法可以直接从外部调用这意味着BeautyEye LNF的外观核心实现无需特定于LookAndFeel的实例.
* <p>
* 也就是说任意外观都可应用本方法所作的外观实现并保证跨平台以使之可灵活应用.
*
* @see org.jb2011.lnf.beautyeye.titlepane.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.tab.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.button.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.separator.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.scroll.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.table.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.textcoms.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.popup.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.toolbar.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.menu.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.internalframe.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.progress.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.radio$cb_btn.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.combox.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.slider.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.tree.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.split.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.spinner.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.list.__UI__#uiImpl()
* @see org.jb2011.lnf.beautyeye.filechooser.__UI__#uiImpl_win()
*/
protected static void implLNF() {
//自定义窗口的L&F实现
org.jackhuang.hmcl.laf.titlepane.__UI__.uiImpl();
//自定义JTabbedPane的L&F实现
org.jackhuang.hmcl.laf.tab.__UI__.uiImpl();
//自定义按钮的L&F实现
org.jackhuang.hmcl.laf.button.__UI__.uiImpl();
//各种杂七杂八的设置
org.jackhuang.hmcl.laf.separator.__UI__.uiImpl();
//自定义滚动条的L&F实现
org.jackhuang.hmcl.laf.scroll.__UI__.uiImpl();
//自定义表格头的L&F实现
org.jackhuang.hmcl.laf.table.__UI__.uiImpl();
//自定义文本组件的L&F实现
org.jackhuang.hmcl.laf.textcoms.__UI__.uiImpl();
//自定义弹出组件包括toolTip组件和弹出菜单等的L&F实现
org.jackhuang.hmcl.laf.popup.__UI__.uiImpl();
//自定义ToggleButton的L&F实现
org.jackhuang.hmcl.laf.toolbar.__UI__.uiImpl();
//自定义菜单项的L&F实现
org.jackhuang.hmcl.laf.menu.__UI__.uiImpl();
//自定义DesktopPane及内部窗体的L&F实现
org.jackhuang.hmcl.laf.internalframe.__UI__.uiImpl();
//自定义进度条的L&F实现
org.jackhuang.hmcl.laf.progress.__UI__.uiImpl();
//自定义单选按钮的L&F实现
org.jackhuang.hmcl.laf.radio$cb_btn.__UI__.uiImpl();
//自定义下拉框的L&F实现
org.jackhuang.hmcl.laf.combox.__UI__.uiImpl();
//自定义JSlider的L&F实现
org.jackhuang.hmcl.laf.slider.__UI__.uiImpl();
//自定义Jtree的L&F实现
org.jackhuang.hmcl.laf.tree.__UI__.uiImpl();
//自定义JSplitPane的L&F实现
org.jackhuang.hmcl.laf.split.__UI__.uiImpl();
//自定义JSpinner的L&F实现
org.jackhuang.hmcl.laf.spinner.__UI__.uiImpl();
//自定义JList的L&F实现
org.jackhuang.hmcl.laf.list.__UI__.uiImpl();
//自定义JFileChooser的L&F实现
org.jackhuang.hmcl.laf.filechooser.__UI__.uiImpl();
}
/**
* Gets the beauty eye lnf platform.
*
* @return {@code new BeautyEyeLookAndFeel()}
*/
public static LookAndFeel getBeautyEyeLNFPlatform() {
return new BeautyEyeLookAndFeel();
}
/**
* 实施BeautyEye外观.<b>开发者使用BeautyEye L&F时应首选本方法.</b>
* <p>
* 本方法会据操作系统类型不同来决定主类是使用BeautyEyeLookAndFeelWin还是BeautyEyeLookAndFeelWin.
* 使用BeautyEye外观时推荐使用本方法来设置外观.之所以有平台不同主类不同的区分是为了
* 在Windows上平台上能更好的使用与操作系统相同的字体等设置.
*
* @throws Exception {@link UIManager#setLookAndFeel(String)}过程中出现的任何异常
* @see #getBeautyEyeLNFStrWindowsPlatform()
* @see #getBeautyEyeLNFPlatform()
* @see org.jb2011.lnf.beautyeye.utils.Platform
*/
public static void launchBeautyEyeLNF() throws Exception {
System.setProperty("sun.java2d.noddraw", "true");
UIManager.setLookAndFeel(getBeautyEyeLNFPlatform());
}
/**
* <b>开发者无需关注本方法.</b>
* <p>
* true表示当前正在使用的窗口边框是不透明的否则表示透明. 本方法目前作为BERootPaneUI中设置窗口是否透明的开关使用.
* <p>
* #### 官方API中存的Bug ####<br>
* 在jdk1.6.0_u33下+win7平台下其它版本是否也有这情况尚未完全验证JFrame窗口
* 被设置成透明后该窗口内所有文本都会被反走样不管你有没有要求反走样真悲具
* 这应该是官方AWTUtilities.setWindowOpaque(..)bug导致的,1.7.0_u6同样存在该问题
* 使用BeautyEye时遇到这样的问题只能自行使用本方法中指定的不透明边框才行这样
* BERootPaneUI类的设置窗口透明的代码就不用执行也就不用触发该bug了但JDialog 不受此bug影响诡异
*
* @return true, if successful
* @since 3.2
*/
public static boolean isFrameBorderOpaque() {
return frameBorderStyle == FrameBorderStyle.osLookAndFeelDecorated
|| frameBorderStyle == FrameBorderStyle.generalNoTranslucencyShadow;
}
/**
* <b>开发者无需关注本方法.</b>
* <p>
* 根据设置的frameBorderStyle来返回正确的窗口边框.
*
* @return
* 当frameBorderStyle=={@link FrameBorderStyle#defaultLookAndFeelDecorated}
* 时返回无意义的BorderFactory.createEmptyBorder()否则返回指定边框对象
*/
public static Border getFrameBorder() {
switch (frameBorderStyle) {
case osLookAndFeelDecorated:
return BorderFactory.createEmptyBorder();
case translucencyAppleLike:
return new BEShadowBorder3();
case translucencySmallShadow:
return new BEShadowBorder();
case generalNoTranslucencyShadow:
default:
return new PlainGrayBorder();
}
}
// /**
// * <b>开发者无需关注本方法.</b>
// * <p>
// * 根据设置的frameBorderStyle来返回正确的窗口边框边角的拖动区大小.
// * <p>
// * <b>重要说明</b>本方法中的边框类型及其对应的边框类必须与方法 {@link #__getFrameBorder()}
// * 完全一致
// *
// * @return 当frameBorderStyle=={@link FrameBorderStyle#defaultLookAndFeelDecorated}
// * 时返回null否则返回指定边框对象
// */
// public static int __getFrameBorder_CORNER_DRAG_WIDTH()
// {
// switch(frameBorderStyle)
// {
// case osLookAndFeelDecorated:
// return 16;
// case translucencyAppleLike:
// return BEShadowBorder3.CORNER_DRAG_WIDTH();
// case translucencySmallShadow:
// return new BEShadowBorder().CORNER_DRAG_WIDTH();
// case generalNoTranslucencyShadow:
// default:
// return new PlainGrayBorder().CORNER_DRAG_WIDTH();
// }
// }
// /**
// * <b>开发者无需关注本方法.</b>
// * <p>
// * 根据设置的frameBorderStyle来返回正确的窗口边框拖动区大小.
// * <p>
// * <b>重要说明</b>本方法中的边框类型及其对应的边框类必须与方法 {@link #__getFrameBorder()}
// * 完全一致
// *
// * @return 当frameBorderStyle=={@link FrameBorderStyle#defaultLookAndFeelDecorated}
// * 时返回null否则返回指定边框对象
// */
// public static int __getFrameBorder_BORDER_DRAG_THICKNESS()
// {
// switch(frameBorderStyle)
// {
// case osLookAndFeelDecorated:
// return 5;
// case translucencyAppleLike:
// return BEShadowBorder3.BORDER_DRAG_THICKNESS();
// case translucencySmallShadow:
// return new BEShadowBorder().BORDER_DRAG_THICKNESS();
// case generalNoTranslucencyShadow:
// default:
// return new PlainGrayBorder().BORDER_DRAG_THICKNESS();
// }
// }
/**
* BeautyEye LNF 的窗口边框样式.
*/
public enum FrameBorderStyle {
/**
* 使用本地系统的窗口装饰样式本样式将能带来最佳性能使用操作系统默认窗口样式.
*/
osLookAndFeelDecorated,
/**
* 使用类似于MacOSX的强烈立体感半透明阴影边框本样式性能尚可视觉效果最佳.
*/
translucencyAppleLike,
/**
* 使用不太强烈立体感半透明阴影边框本样式性能尚可视觉效果较soft.
*/
translucencySmallShadow,
/**
* 使用不透明的普通边框这是本LNF在Java1.5版默认使用的样式因为java1.5不支持窗口透明
*/
generalNoTranslucencyShadow
}
/**
* <b>开发者暂时无需关注此接口.</b>
* <p>
* 实现了此接口的UI类意味着用户可以通过自行设置诸如border等 取消默认的NainePatch图实现的边框填充背景填充等具体设置哪
* 些东西可以取消默认的NinePatch图填充的方式详见各自的类注释
*/
public interface __UseParentPaintSurported {
/**
* 是否使用父类的绘制实现方法true表示是.
* <p>
* 因为在BE LNF中进度条和背景都是使用N9图比如没法通过设置JProgressBar的背景色和前景
* 色来控制进度条的颜色本方法的目的就是当用户设置了进度条的Background或Foreground 时告之本实现类不使用BE
* LNF中默认的N9图填充绘制而改用父类中的方法父类中的方法
* 就可以支持颜色的设置罗只是丑点但总归是能适应用户的需求场景要求其实用户完全可以 通过JProgressBar.setUI(new
* MetalProgressBar())方式来自定义进度的UI哦.
*
* @return true, if is use parent paint
*/
boolean isUseParentPaint();
}
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BeautyEyeLookAndFeel.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf;
import java.awt.Font;
import java.util.Enumeration;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.metal.MetalLookAndFeel;
/**
* <p>
* BeautyEye Swing外观实现方案 - 跨平台通用外观实现主类.<br>
* <p>
* 本主题主类仅供跨平台时使用它可用于Java支持的所有操作系统.
*
* 如果要继承BasicLookAndFeel实现跨平台lnf 则还需要做更多的工作目前
* 跨平台时干脆继承MetalLookAndFeel以便站在巨人的肩膀上节省一些工作量
*
* @author Jack Jiang(jb2011@163.com)
* @version 1.0
*/
public class BeautyEyeLookAndFeel extends MetalLookAndFeel {
private static void initGlobalFont(Font font) {
FontUIResource fontRes = new FontUIResource(font);
for (Enumeration<Object> keys = UIManager.getDefaults().keys();
keys.hasMoreElements(); ) {
Object key = keys.nextElement();
Object value = UIManager.get(key);
if (value instanceof FontUIResource) {
UIManager.put(key, fontRes);
}
}
}
public BeautyEyeLookAndFeel() {
super();
// //本属性仅对windows平台有效 -> Jack Jiang最终证实没效果
// UIManager.put("Application.useSystemFontSettings", Boolean.TRUE);
//取消Metal LNF中默认的粗体字
UIManager.put("swing.boldMetal", Boolean.FALSE);
//此项如是true则将会为TabbedPane的内容面板填充天蓝色背景
UIManager.put("TabbedPane.contentOpaque", Boolean.FALSE);
//此项如是true则将会为TabbedPane的标签填充天蓝色背景
UIManager.put("TabbedPane.tabsOpaque", Boolean.FALSE);
initGlobalFont(new Font("微软雅黑", Font.PLAIN, 12));
BeautyEyeLNFHelper.implLNF();
}
@Override
public String getName() {
return "BeautyEye";
}
@Override
public String getID() {
return "BeautyEye";
}
@Override
public String getDescription() {
return "BeautyEye L&F developed by Jack Jiang(jb2011@163.com).";
}
/**
* Gets the supports window decorations.
*
* @return the supports window decorations {@inheritDoc}
*/
@Override
public boolean getSupportsWindowDecorations() {
return true;
}
@Override
public boolean isNativeLookAndFeel() {
return false;
}
@Override
public boolean isSupportedLookAndFeel() {
return true;
}
@Override
protected void initComponentDefaults(UIDefaults table) {
super.initComponentDefaults(table);
initOtherResourceBundle(table);
}
/**
* Initialize the defaults table with the name of the other ResourceBundle
* used for getting localized defaults.
*/
protected void initOtherResourceBundle(UIDefaults table) {
table.addResourceBundle("org.jb2011.lnf.beautyeye.resources.beautyeye");
}
}

View File

@ -1,135 +0,0 @@
/*
* Copyright 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.
*/
package org.jackhuang.hmcl.laf;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.text.ParseException;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.UIDefaults;
import javax.swing.plaf.synth.SynthLookAndFeel;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.util.sys.IOUtils;
import org.jackhuang.hmcl.util.ui.GraphicsUtils;
/**
*
* @author huangyuhui
*/
public class HelloMinecraftLookAndFeel extends SynthLookAndFeel {
public static final Map<String, String> DEFAULT_SETTINGS = LAFTheme.BLUE.settings;
/**
* Creates a new instance of NimbusLookAndFeel
*
* @throws java.text.ParseException error parsing the xml, it must not
* happen.
*/
public HelloMinecraftLookAndFeel() throws ParseException {
this(DEFAULT_SETTINGS);
}
public HelloMinecraftLookAndFeel(Map<String, String> settings) throws ParseException {
try {
try (InputStream is = HelloMinecraftLookAndFeel.class.getResourceAsStream("/org/jackhuang/hmcl/laf/synth.xml")) {
String s = IOUtils.toString(is, "UTF-8");
for (Map.Entry<String, String> ss : settings.entrySet())
s = s.replace("${" + ss.getKey() + "}", ss.getValue());
load(new ByteArrayInputStream(s.getBytes("UTF-8")), HelloMinecraftLookAndFeel.class);
}
} catch (Throwable ex) {
HMCLog.err("This fucking exception should not happen. Retry backup solution.", ex);
try {
try (InputStream is = HelloMinecraftLookAndFeel.class.getResourceAsStream("/org/jackhuang/hmcl/laf/synth_backup.xml")) {
load(is, HelloMinecraftLookAndFeel.class);
}
} catch (Throwable e) {
HMCLog.err("User fault", e);
}
}
}
UIDefaults uiDefaults;
@Override
public UIDefaults getDefaults() {
if (uiDefaults != null)
return uiDefaults;
uiDefaults = super.getDefaults();
//ui.put("Table.selectionForeground", new ColorUIResource(Color.red));
//ui.put("Table.focusCellForeground", new ColorUIResource(Color.red));
//ui.put("TabbedPane.isTabRollover", false);
//ui.put("ComboBox.selectionBackground", new ColorUIResource(Color.red));
//ui.put("List.background", new ColorUIResource(Color.red));
//uiDefaults.put("TabbedPane.selectedLabelShift", 0);
uiDefaults.put("Table.selectionBackground", Color.red);
return uiDefaults;
}
/**
* Return a short string that identifies this look and feel.
*
* @return a short string identifying this look and feel.
*/
@Override
public String getName() {
return "HelloMinecraftLookAndFeel";
}
/**
* Return a string that identifies this look and feel.
*
* @return a short string identifying this look and feel.
*/
@Override
public String getID() {
return "HelloMinecraftLookAndFeel";
}
/**
* Returns a textual description of this look and feel.
*
* @return textual description of this look and feel.
*/
@Override
public String getDescription() {
return "HelloMinecraftLookAndFeel";
}
/**
* Load an image using ImageIO from resource in
* org.jdesktop.swingx.plaf.nimbus.images. Catches and prints all Exceptions
* so that it can safely be used in a static context.
*
* @param imgName The name of the image to load, eg. "border.png"
*
* @return The loaded image
*/
public static BufferedImage loadImage(String imgName) {
try {
return ImageIO.read(GraphicsUtils.class.getClassLoader().getResource("org/jackhuang/hmcl/laf/images/" + imgName));
} catch (Exception e) {
System.err.println("Error loading image \"org/jackhuang/hmcl/laf/images/" + imgName + "\"");
e.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,180 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hmcl.laf.utils;
import java.util.HashMap;
import org.jb2011.ninepatch4j.NinePatch;
/**
*
* @author huang
*/
public class Icon9Factory extends RawCache<NinePatch> {
/**
* 相对路径根默认是相对于本类的相对物理路径.
*/
public final static String IMGS_ROOT = "imgs/np";
@Override
protected NinePatch getResource(String relativePath, Class baseClass) {
return NinePatchHelper.createNinePatch(baseClass.getResource(relativePath), false);
}
public Icon9Factory(String namespace) {
ns = namespace;
init();
}
String ns;
/**
* Gets the raw.
*
* @param relativePath the relative path
* @return the raw
*/
public NinePatch getRaw(String relativePath) {
return getRaw(relativePath, this.getClass());
}
HashMap<String, NinePatch> icons = new HashMap<>();
protected void put(String namespace, String key, String filename) {
if (!ns.equals(namespace))
return;
icons.put(namespace + ":" + key, getRaw(IMGS_ROOT + "/" + filename + ".9.png"));
}
public NinePatch get(String key) {
return icons.get(ns + ":" + key);
}
public NinePatch get(String key, String state) {
return Icon9Factory.this.get(concat(key, state));
}
public NinePatch getWithEnabled(String key, boolean enabled) {
return get(key, enabled ? "" : "disabled");
}
public NinePatch getWithHorizontal(String key, boolean isHorizontal) {
return get(key, isHorizontal ? "" : "vertical");
}
public NinePatch getWithButtonState(String key, boolean enabled, boolean pressed) {
return get(key, (enabled ? (pressed ? "pressed" : "normal") : "disabled"));
}
public NinePatch getWithScrollState(String key, boolean pressed, boolean over) {
return get(key, (pressed ? "pressed" : (over ? "rollover" : "")));
}
public NinePatch getWithComboState(String key, boolean enabled, boolean pressed, boolean over) {
return get(key, (enabled ? (pressed ? "pressed" : (over ? "rollover" : "normal")) : "disabled"));
}
private String concat(String a, String b) {
if (a.isEmpty() && b.isEmpty())
return "";
else if (a.isEmpty())
return b;
else if (b.isEmpty())
return a;
else
return a + "_" + b;
}
private void init() {
put("slider_track", "", "slider_track2");
put("slider_track", "vertical", "slider_track2_v");
put("slider_track", "disabled", "slider_track2_dark");
put("slider_track", "vertical_disabled", "slider_track2_v_dark");
put("slider_track", "foreground", "slider_track2_forgroud");
put("slider_track", "foreground_disabled", "slider_track2_forgroud_disable");
put("slider_track", "vertical_foreground", "slider_track2_forgroud_v");
put("slider_track", "vertical_foreground_disabled", "slider_track2_forgroud_v_disable");
put("button_arrow", "normal", "button_arrow");
put("button_arrow", "pressed", "button_arrow_pressed");
put("button_arrow", "rollover", "button_arrow_rollover");
put("button_arrow", "disabled", "button_arrow_disable");
put("progress_bar", "bg", "progress_bar_bg");
put("progress_bar", "bg_vertical", "progress_bar_bg_v");
put("progress_bar", "green", "progress_bar_green");
put("progress_bar", "blue_vertical", "progress_bar_grean_v");
put("split_touch", "bg1", "split_touch_bg1");
put("list", "selected_icon_bg", "list_cell_selected_bg2");
put("spinner", "", "spinner1_bg");
put("spinner", "button_up", "spinner1_btn_up_bg");
put("spinner", "button_down", "spinner1_btn_down_bg");
put("spinner", "button_up_pressed", "spinner1_btn_up_pressed_bg");
put("spinner", "button_down_pressed", "spinner1_btn_down_pressed_bg");
put("spinner", "disabled", "spinner1_disable_bg");
put("button", "normal", "btn_special_default");
put("button", "disabled", "btn_special_disabled");
put("button", "pressed", "btn_general_pressed");
put("button", "rollover", "btn_general_rover");
put("toggle_button", "selected", "toggle_button_selected");
put("toggle_button", "rollover", "toggle_button_rover");
put("scroll_bar", "vertical", "scroll_bar_v");
put("scroll_bar", "vertical_rollover", "scroll_bar_rover_v");
put("scroll_bar", "vertical_pressed", "scroll_bar_pressed_v");
put("scroll_bar", "horizontal", "scroll_bar_h");
put("scroll_bar", "horizontal_rollover", "scroll_bar_rover_h");
put("scroll_bar", "horizontal_pressed", "scroll_bar_rover_h");
put("scroll_bar", "arrow_bottom", "arrow_toBottom");
put("scroll_bar", "arrow_top", "arrow_toTop");
put("scroll_bar", "arrow_left", "arrow_toLeft");
put("scroll_bar", "arrow_right", "arrow_toRight");
put("scroll_bar", "arrow_bottom_rollover", "arrow_toBottom_rover");
put("scroll_bar", "arrow_top_rollover", "arrow_toTop_rover");
put("scroll_bar", "arrow_left_rollover", "arrow_toLeft_rover");
put("scroll_bar", "arrow_right_rollover", "arrow_toRight_rover");
put("scroll_bar", "scroll_pane_border", "scroll_pane_bg1");
put("popup", "popup", "shadow_bg_popup");
put("popup", "tooltip", "shadow_bg_tooltip2");
put("table", "scroll_border", "table_scrollborder1");
put("table", "header_cell", "table_header_bg1");
put("table", "header_cell_separator", "table_header_separator1");
put("text", "normal", "bg_login_text_normal");
put("text", "pressed", "bg_login_text_pressed");
put("text", "disabled", "bg_login_text_disable");
put("text", "white", "null_white_bg");
put("toolbar", "north", "toolbar_bg1");
put("toolbar", "south", "toolbar_bg1_SOUTH");
put("toolbar", "west", "toolbar_bg1_WEST");
put("toolbar", "east", "toolbar_bg1_EAST");
put("menu", "selected", "menu_bg");
put("widget", "panel", "query_item_bg_2");
put("widget", "hint_light_blue", "hint_bg_lightblue");
put("widget", "hint_light_gray", "hint_bg_lightblue_gray");
put("widget", "tips", "tips_bg");
put("widget", "orange_balloon", "orange_baloon1");
put("widget", "border_shadow1", "shadow1");
put("widget", "border_shadow2", "shadow2");
put("widget", "border_plain_gray", "plain_gray1");
put("widget", "border_shadow3", "frame_shadow_border4");
put("combo", "normal", "combo_normal");
put("combo", "disabled", "combo_disabled");
put("combo", "rollover", "combo_over");
put("combo", "pressed", "combo_pressed");
}
}

View File

@ -0,0 +1,150 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hmcl.laf.utils;
import java.util.HashMap;
import javax.swing.ImageIcon;
/**
*
* @author huang
*/
public class IconFactory extends RawCache<ImageIcon> {
/**
* 相对路径根默认是相对于本类的相对物理路径.
*/
public final static String IMGS_ROOT = "imgs";
public IconFactory(String namespace) {
ns = namespace;
init();
}
String ns;
@Override
protected ImageIcon getResource(String relativePath, Class baseClass) {
return new ImageIcon(baseClass.getResource(relativePath));
}
/**
* Gets the image.
*
* @param relativePath the relative path
* @return the image
*/
protected ImageIcon getImage(String relativePath) {
return getRaw(relativePath, IconFactory.class);
}
HashMap<String, ImageIcon> icons = new HashMap<>();
protected void put(String namespace, String key, String filename) {
if (!ns.equals(namespace))
return;
icons.put(namespace + ":" + key, getImage(IMGS_ROOT + "/" + filename + ".png"));
}
public ImageIcon get(String... states) {
String s = "";
for (String k : states)
s = concat(s, k);
return icons.get(ns + ":" + s);
}
public ImageIcon getWithButtonState(String key, boolean enabled, boolean pressed) {
return get(key, (enabled ? (pressed ? "pressed" : "normal") : "disabled"));
}
private String concat(String a, String b) {
if (a.isEmpty() && b.isEmpty())
return "";
else if (a.isEmpty())
return b;
else if (b.isEmpty())
return a;
else
return a + "_" + b;
}
void init() {
put("menu", "radio_check", "RadioButtonMenuItemCheckIcon2");
put("menu", "radio_normal", "RadioButtonMenuItemCheckIcon_none");
put("menu", "check_selected", "checkbox_menuitem_selected_normal");
put("menu", "check_none", "checkbox_menuitem_none");
put("internal_frame", "close", "frame_close_over");
put("internal_frame", "min", "frame_windowize_over");
put("internal_frame", "max", "frame_maximize_over");
put("internal_frame", "iconify", "frame_minimize_over");
put("internal_frame", "icon", "ifi1");
put("radio", "disabled", "radio_btn_disabled_selected");
put("radio", "normal", "radio_btn_selected");
put("radio", "pressed", "radio_btn_selected_pressed");
put("radio", "over", "radio_btn_selected_over");
put("radio", "unchecked_disabled", "radio_btn_disabled_normal");
put("radio", "unchecked_normal", "radio_btn");
put("radio", "unchecked_pressed", "radio_btn_pressed");
put("radio", "unchecked_over", "radio_btn_over");
put("check", "disabled", "checkbox_on_disabled");
put("check", "normal", "checkbox_on");
put("check", "pressed", "checkbox_on_pressed");
put("check", "over", "checkbox_on_over");
put("check", "unchecked_disabled", "checkbox_off_disabled");
put("check", "unchecked_normal", "checkbox_off");
put("check", "unchecked_pressed", "checkbox_off_pressed");
put("check", "unchecked_over", "checkbox_off_over");
put("menu_radio", "checked", "RadioButtonMenuItemCheckIcon2");
put("menu_radio", "normal", "RadioButtonMenuItemCheckIcon_none");
put("menu_check", "checked", "checkbox_menuitem_selected_normal");
put("menu_check", "normal", "checkbox_menuitem_none");
put("table", "descending_sort", "desc2");
put("table", "ascending_sort", "asc2");
put("tree", "open", "treeDefaultOpen1");
put("tree", "closed", "treeDefaultClosed1");
put("tree", "leaf", "leaf1");
put("tree", "expanded", "a");
put("tree", "collapsed", "b");
put("option_pane", "warn", "warn");
put("option_pane", "error", "error");
put("option_pane", "info", "info");
put("option_pane", "question", "question");
put("slider", "", "slider_tick1");
put("slider", "disabled", "slider_tick1_dark");
put("slider", "vertical", "slider_tick1_v");
put("slider", "vertical_disabled", "slider_tick1_v_dark");
put("slider", "notriangle", "slider_tick1_notrangle");
put("slider", "notriangle_disabled", "slider_tick1_notrangle_dark");
put("slider", "notriangle_vertical", "slider_tick1_notrangle_v");
put("slider", "notriangle_vertical_disabled", "slider_tick1_notrangle_v_dark");
put("frame", "close", "frame_close_normal");
put("frame", "close_over", "frame_close_rover");
put("frame", "close_pressed", "frame_close_pressed");
put("frame", "min", "frame_maxwin");
put("frame", "min_over", "frame_maxwin_rover");
put("frame", "min_pressed", "frame_maxwin_pressed");
put("frame", "max", "frame_max_normal");
put("frame", "max_over", "frame_max_rover");
put("frame", "max_pressed", "frame_max_pressed");
put("frame", "iconify", "frame_min_normal");
put("frame", "iconify_over", "frame_min_rover");
put("frame", "iconify_pressed", "frame_min_pressed");
put("frame", "icon", "default_frame_icon");
put("frame", "setup", "frame_setup_normal");
put("frame", "title_active", "head_bg");
put("frame", "title_inactive", "head_inactive");
}
}

View File

@ -31,6 +31,9 @@ public final class LAFTheme {
put("Customized.TabbedPaneTab.selected_foreground", "#106CA3");
put("Customized.ComboBox.selected_background", "#A0D8F0");
put("Customized.MainFrame.background", "#106CA3");
put("TabbedPane.selectedForeground", "#106CA3");
put("TextField.focused", "#106CA3");
put("MenuItem.selectionBackground", "#106CA3");
put("Customized.MainFrame.selected_background", "#0C5E91");
put("Customized.MainFrame.background_image", "background.jpg");
}
@ -40,6 +43,9 @@ public final class LAFTheme {
put("Customized.TabbedPaneTab.selected_foreground", "#1ABC9C");
put("Customized.ComboBox.selected_background", "#1ABC9C");
put("Customized.MainFrame.background", "#1ABC9C");
put("TabbedPane.selectedForeground", "#1ABC9C");
put("TextField.focused", "#1ABC9C");
put("MenuItem.selectionBackground", "#1ABC9C");
put("Customized.MainFrame.selected_background", "#16A085");
put("Customized.MainFrame.background_image", "background.jpg");
}
@ -49,6 +55,9 @@ public final class LAFTheme {
put("Customized.TabbedPaneTab.selected_foreground", "#9B59B6");
put("Customized.ComboBox.selected_background", "#9B59B6");
put("Customized.MainFrame.background", "#9B59B6");
put("TabbedPane.selectedForeground", "#9B59B6");
put("TextField.focused", "#9B59B6");
put("MenuItem.selectionBackground", "#9B59B6");
put("Customized.MainFrame.selected_background", "#8E44AD");
put("Customized.MainFrame.background_image", "background.jpg");
}
@ -58,6 +67,9 @@ public final class LAFTheme {
put("Customized.TabbedPaneTab.selected_foreground", "#34495E");
put("Customized.ComboBox.selected_background", "#34495E");
put("Customized.MainFrame.background", "#34495E");
put("TabbedPane.selectedForeground", "#34495E");
put("TextField.focused", "#34495E");
put("MenuItem.selectionBackground", "#34495E");
put("Customized.MainFrame.selected_background", "#2C3E50");
put("Customized.MainFrame.background_image", "background.jpg");
}
@ -67,6 +79,9 @@ public final class LAFTheme {
put("Customized.TabbedPaneTab.selected_foreground", "#E67E22");
put("Customized.ComboBox.selected_background", "#F39C12");
put("Customized.MainFrame.background", "#E67E22");
put("TabbedPane.selectedForeground", "#E67E22");
put("TextField.focused", "#E67E22");
put("MenuItem.selectionBackground", "#E67E22");
put("Customized.MainFrame.selected_background", "#D35400");
put("Customized.MainFrame.background_image", "background.jpg");
}
@ -76,6 +91,9 @@ public final class LAFTheme {
put("Customized.TabbedPaneTab.selected_foreground", "#E74C3C");
put("Customized.ComboBox.selected_background", "#E74C3C");
put("Customized.MainFrame.background", "#E74C3C");
put("TabbedPane.selectedForeground", "#E74C3C");
put("TextField.focused", "#E74C3C");
put("MenuItem.selectionBackground", "#E74C3C");
put("Customized.MainFrame.selected_background", "#C0392B");
put("Customized.MainFrame.background_image", "background.jpg");
}

View File

@ -0,0 +1,178 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* MySwingUtilities2.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.utils;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import javax.swing.JComponent;
/**
* 本类中的方法一一对应于SUN未公开的类SwingUtilities2中的方法.
*
* 部分代码摘自JDK 1.5.
*
* @author Jack Jiang(jb2011@163.com)
* @author huangyuhui
*/
public class MySwingUtilities2 {
/**
* Returns the FontMetrics for the current Font of the passed in Graphics.
* This method is used when a Graphics is available, typically when
* painting. If a Graphics is not available the JComponent method of the
* same name should be used.
* <p>
* Callers should pass in a non-null JComponent, the exception to this is if
* a JComponent is not readily available at the time of painting.
* <p>
* This does not necessarily return the FontMetrics from the Graphics.
*
* @param c JComponent requesting FontMetrics, may be null
* @param g Graphics Graphics
* @return the font metrics
*/
public static FontMetrics getFontMetrics(JComponent c, Graphics g) {
return getFontMetrics(c, g, g.getFont());
}
/**
* Returns the FontMetrics for the specified Font. This method is used when
* a Graphics is available, typically when painting. If a Graphics is not
* available the JComponent method of the same name should be used.
* <p>
* Callers should pass in a non-null JComonent, the exception to this is if
* a JComponent is not readily available at the time of painting.
* <p>
* This does not necessarily return the FontMetrics from the Graphics.
*
* @param c Graphics Graphics
* @param g the g
* @param font Font to get FontMetrics for
* @return the font metrics
*/
public static FontMetrics getFontMetrics(JComponent c, Graphics g,
Font font) {
if (c != null)
// Note: We assume that we're using the FontMetrics
// from the widget to layout out text, otherwise we can get
// mismatches when printing.
return c.getFontMetrics(font);
return Toolkit.getDefaultToolkit().getFontMetrics(font);
}
/**
* Returns the width of the passed in String.
*
* @param c JComponent that will display the string, may be null
* @param fm FontMetrics used to measure the String width
* @param string String to get the width of
* @return the int
*/
public static int stringWidth(JComponent c, FontMetrics fm, String string) {
return fm.stringWidth(string);
}
/**
* Draws the string at the specified location.
*
* @param c JComponent that will display the string, may be null
* @param g Graphics to draw the text to
* @param text String to display
* @param x X coordinate to draw the text at
* @param y Y coordinate to draw the text at
*/
public static void drawString(JComponent c, Graphics g, String text,
int x, int y) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.drawString(text, x, y);
}
/**
* Draws the string at the specified location underlining the specified
* character.
*
* @param c JComponent that will display the string, may be null
* @param g Graphics to draw the text to
* @param text String to display
* @param underlinedIndex Index of a character in the string to underline
* @param x X coordinate to draw the text at
* @param y Y coordinate to draw the text at
*/
public static void drawStringUnderlineCharAt(JComponent c, Graphics g,
String text, int underlinedIndex, int x, int y) {
drawString(c, g, text, x, y);
if (underlinedIndex >= 0 && underlinedIndex < text.length()) {
// PENDING: this needs to change.
FontMetrics fm = g.getFontMetrics();
int underlineRectX = x + stringWidth(c,
fm, text.substring(0, underlinedIndex));
int underlineRectY = y;
int underlineRectWidth = fm.charWidth(text.
charAt(underlinedIndex));
int underlineRectHeight = 1;
g.fillRect(underlineRectX, underlineRectY + 1,
underlineRectWidth, underlineRectHeight);
}
}
/**
* Clips the passed in String to the space provided.
*
* @param c JComponent that will display the string, may be null
* @param fm FontMetrics used to measure the String width
* @param string String to display
* @param availTextWidth Amount of space that the string can be drawn in
* @return Clipped string that can fit in the provided space.
*/
public static String clipStringIfNecessary(JComponent c, FontMetrics fm,
String string, int availTextWidth) {
if ((string == null) || (string.equals("")))
return "";
int textWidth = stringWidth(c, fm, string);
if (textWidth > availTextWidth)
return clipString(c, fm, string, availTextWidth);
return string;
}
/**
* Clips the passed in String to the space provided. NOTE: this assumes the
* string does not fit in the available space.
*
* @param c JComponent that will display the string, may be null
* @param fm FontMetrics used to measure the String width
* @param string String to display
* @param availTextWidth Amount of space that the string can be drawn in
* @return Clipped string that can fit in the provided space.
*/
public static String clipString(JComponent c, FontMetrics fm,
String string, int availTextWidth) {
// c may be null here.
String clipString = "...";
int width = stringWidth(c, fm, clipString);
// NOTE: This does NOT work for surrogate pairs and other fun
// stuff
int nChars = 0;
for (int max = string.length(); nChars < max; nChars++) {
width += fm.charWidth(string.charAt(nChars));
if (width > availTextWidth)
break;
}
string = string.substring(0, nChars) + clipString;
return string;
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* NinePatchHelper.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.utils;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.jb2011.ninepatch4j.NinePatch;
/**
* NinePatch图辅助工厂类.
*
* @author Jack Jiang(jb2011@163.com), 2011-12-22
* @version 1.0
*/
public class NinePatchHelper {
/**
* Creates the nine patch.
*
* @param fileUrl the file url
* @param convert the convert
* @return the nine patch
* @see NinePatch#load(URL, boolean)
*/
public static NinePatch createNinePatch(URL fileUrl, boolean convert) {
try {
return NinePatch.load(fileUrl, convert);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Creates the nine patch.
*
* @param stream the stream
* @param is9Patch the is9 patch
* @param convert the convert
* @return the nine patch
* @throws IOException Signals that an I/O exception has occurred.
* @see NinePatch#load(InputStream, boolean, boolean)
*/
public static NinePatch createNinePatch(InputStream stream, boolean is9Patch, boolean convert) throws IOException {
return NinePatch.load(stream, is9Patch, convert);
}
/**
* Creates the nine patch.
*
* @param image the image
* @param is9Patch the is9 patch
* @param convert the convert
* @return the nine patch
* @see NinePatch#load(BufferedImage, boolean, boolean)
*/
public static NinePatch createNinePatch(BufferedImage image, boolean is9Patch, boolean convert) {
return NinePatch.load(image, is9Patch, convert);
}
}

View File

@ -0,0 +1,66 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hmcl.laf.utils;
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.DimensionUIResource;
import javax.swing.plaf.InsetsUIResource;
/**
*
* @author huang
*/
public class UI {
protected static void put(String key, int i) {
UIManager.put(key, i);
}
protected static void put(String key, boolean b) {
UIManager.put(key, b);
}
protected static void put(String key, Color c) {
UIManager.put(key, new ColorUIResource(c));
}
protected static void put(String key, Border b) {
UIManager.put(key, new BorderUIResource(b));
}
protected static void putDim(String key, int w, int h) {
UIManager.put(key, new DimensionUIResource(h, h));
}
protected static void putInsets(String key, int top, int left, int bottom, int right) {
UIManager.put(key, new InsetsUIResource(top, left, bottom, right));
}
protected static void putBorder(String key) {
UIManager.put(key, BorderFactory.createEmptyBorder());
}
protected static void putBorder(String key, int top, int left, int bottom, int right) {
UIManager.put(key, new BorderUIResource(BorderFactory.createEmptyBorder(top, left, bottom, right)));
}
protected static void putColor(String key, int r, int g, int b) {
put(key, new Color(r, g, b));
}
protected static void putColor(String key, int r, int g, int b, int a) {
put(key, new Color(r, g, b, a));
}
protected static void put(String key, Class c) {
UIManager.put(key, c.getName());
}
}

View File

@ -0,0 +1,147 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* WinUtils.java at 2015-2-1 20:25:37, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.utils;
import java.awt.Color;
import java.awt.Component;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.UIManager;
/**
* The Class WinUtils.
*
* @see com.sun.java.swing.plaf.windows.WindowsGraphicsUtils
*/
public class WinUtils {
//* copy from WindowsLookAndFeel START 未做修改
// Toggle flag for drawing the mnemonic state
/**
* The is mnemonic hidden.
*/
private static boolean isMnemonicHidden = true;
/**
* Gets the state of the hide mnemonic flag. This only has meaning if this
* feature is supported by the underlying OS.
*
* @return true if mnemonics are hidden, otherwise, false
* @see #setMnemonicHidden
* @since 1.4
*/
public static boolean isMnemonicHidden() {
if (UIManager.getBoolean("Button.showMnemonics") == true)
// Do not hide mnemonics if the UI defaults do not support this
isMnemonicHidden = false;
return isMnemonicHidden;
}
//* copy from WindowsLookAndFeel END
//* copy from WindowsGraphicsUtils START (modified by jack jiang)
/**
* Renders a text String in Windows without the mnemonic. This is here
* because the WindowsUI hiearchy doesn't match the Component heirarchy. All
* the overriden paintText methods of the ButtonUI delegates will call this
* static method.
* <p>
*
* @param g Graphics context
* @param b Current button to render
* @param textRect Bounding rectangle to render the text.
* @param text String to render
* @param textShiftOffset the text shift offset
*/
public static void paintText(Graphics g, AbstractButton b,
Rectangle textRect, String text,
int textShiftOffset) {
FontMetrics fm = MySwingUtilities2.getFontMetrics(b, g);
int mnemIndex = b.getDisplayedMnemonicIndex();
// W2K Feature: Check to see if the Underscore should be rendered.
if (isMnemonicHidden() == true)
mnemIndex = -1;
paintClassicText(b, g, textRect.x + textShiftOffset,
textRect.y + fm.getAscent() + textShiftOffset,
text, mnemIndex);
}
/**
* Paint classic text.
*
* @param b the b
* @param g the g
* @param x the x
* @param y the y
* @param text the text
* @param mnemIndex the mnem index
*/
static void paintClassicText(AbstractButton b, Graphics g, int x, int y,
String text, int mnemIndex) {
ButtonModel model = b.getModel();
/* Draw the Text */
Color color = b.getForeground();
if (model.isEnabled()) {
/**
* * paint the text normally
*/
if (!(b instanceof JMenuItem && model.isArmed())
&& !(b instanceof JMenu && (model.isSelected() || model.isRollover())))
/* We shall not set foreground color for selected menu or
* armed menuitem. Foreground must be set in appropriate
* Windows* class because these colors passes from
* BasicMenuItemUI as protected fields and we can't
* reach them from this class */
g.setColor(b.getForeground());
MySwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, x, y);
} else {
/**
* * paint the text disabled **
*/
color = UIManager.getColor("Button.shadow");
Color shadow = UIManager.getColor("Button.disabledShadow");
if (model.isArmed())
color = UIManager.getColor("Button.disabledForeground");
else {
if (shadow == null)
shadow = b.getBackground().darker();
g.setColor(shadow);
MySwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, x + 1, y + 1);
}
if (color == null)
color = b.getBackground().brighter();
g.setColor(color);
MySwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, x, y);
}
}
//* copy from WindowsGraphicsUtils END (modified by jack jiang)
//* copy from WindowsGraphicsUtils START
/**
* 是否组件的排列方向是从左到右.
*
* @param c the c
* @return true, if is left to right
*/
public static boolean isLeftToRight(Component c) {
return c.getComponentOrientation().isLeftToRight();
}
//* copy from WindowsGraphicsUtils END
}

View File

@ -0,0 +1,334 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEButtonUI.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.button;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JRadioButton;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.InsetsUIResource;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.text.JTextComponent;
import org.jackhuang.hmcl.laf.BEUtils;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
/**
* JButton的UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
* @version 1.0
* @see com.sun.java.swing.plaf.windows.WindowsButtonUI
*/
public class BEButtonUI extends BasicButtonUI {
private static final Icon9Factory ICON_9 = new Icon9Factory("button");
private final static BEButtonUI INSTANCE = new BEButtonUI();
/**
* The dashed rect gap x.
*/
protected int dashedRectGapX;
/**
* The dashed rect gap y.
*/
protected int dashedRectGapY;
/**
* The dashed rect gap width.
*/
protected int dashedRectGapWidth;
/**
* The dashed rect gap height.
*/
protected int dashedRectGapHeight;
/**
* The focus color.
*/
protected Color focusColor;
/**
* The defaults_initialized.
*/
private boolean defaults_initialized = false;
// ********************************
// Create PLAF
// ********************************
public static ComponentUI createUI(JComponent c) {
if (c instanceof CustomButton)
return new CustomButtonUI();
return INSTANCE;
}
// ********************************
// Defaults
// ********************************
@Override
protected void installDefaults(AbstractButton b) {
super.installDefaults(b);
LookAndFeel.installProperty(b, "opaque", Boolean.FALSE);
if (!defaults_initialized) {
String pp = getPropertyPrefix();
dashedRectGapX = UIManager.getInt(pp + "dashedRectGapX");
dashedRectGapY = UIManager.getInt(pp + "dashedRectGapY");
dashedRectGapWidth = UIManager.getInt(pp + "dashedRectGapWidth");
dashedRectGapHeight = UIManager.getInt(pp + "dashedRectGapHeight");
focusColor = UIManager.getColor(pp + "focus");
defaults_initialized = true;
}
{
LookAndFeel.installProperty(b, "rolloverEnabled", Boolean.TRUE);
}
}
@Override
protected void uninstallDefaults(AbstractButton b) {
super.uninstallDefaults(b);
defaults_initialized = false;
}
/**
* Gets the focus color.
*
* @return the focus color
*/
protected Color getFocusColor() {
return focusColor;
}
// ********************************
// Paint Methods
// ********************************
@Override
protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) {
// focus painted same color as text on Basic??
int width = b.getWidth();
int height = b.getHeight();
g.setColor(getFocusColor());
//** modified by jb2011绘制虚线方法改成可以设置虚线步进的方法步进设为2则更好看一点
// BasicGraphicsUtils.drawDashedRect(g, dashedRectGapX, dashedRectGapY,
// width - dashedRectGapWidth, height - dashedRectGapHeight);
// 绘制虚线框
BEUtils.drawDashedRect(g, dashedRectGapX, dashedRectGapY,
width - dashedRectGapWidth, height - dashedRectGapHeight);
// 绘制虚线框的半透明白色立体阴影半透明的用处在于若隐若现的效果比纯白要来的柔和的多
g.setColor(new Color(255, 255, 255, 50));
// 立体阴影就是向右下偏移一个像素实现的
BEUtils.drawDashedRect(g, dashedRectGapX + 1, dashedRectGapY + 1,
width - dashedRectGapWidth, height - dashedRectGapHeight);
}
// ********************************
// Layout Methods
// ********************************
@Override
public Dimension getPreferredSize(JComponent c) {
Dimension d = super.getPreferredSize(c);
/* Ensure that the width and height of the button is odd,
* to allow for the focus line if focus is painted
*/
AbstractButton b = (AbstractButton) c;
if (d != null && b.isFocusPainted()) {
if (d.width % 2 == 0)
d.width += 1;
if (d.height % 2 == 0)
d.height += 1;
}
return d;
}
/* These rectangles/insets are allocated once for all
* ButtonUI.paint() calls. Re-using rectangles rather than
* allocating them in each paint call substantially reduced the time
* it took paint to run. Obviously, this method can't be re-entered.
*/
// private static Rectangle viewRect = new Rectangle();
@Override
public void paint(Graphics g, JComponent c) {
paintXPButtonBackground(g, c);
super.paint(g, c);
}
/**
* Paint xp button background.
*
* @param nomalColor the nomal color
* @param g the g
* @param c the c
*/
public static void paintXPButtonBackground(Graphics g, JComponent c) {
AbstractButton b = (AbstractButton) c;
boolean toolbar = b.getParent() instanceof JToolBar;
if (b.isContentAreaFilled()) {
ButtonModel model = b.getModel();
Dimension d = c.getSize();
int dx = 0;
int dy = 0;
int dw = d.width;
int dh = d.height;
Border border = c.getBorder();
Insets insets;
if (border != null)
// Note: The border may be compound, containing an outer
// opaque border (supplied by the application), plus an
// inner transparent margin border. We want to size the
// background to fill the transparent part, but stay
// inside the opaque part.
insets = BEButtonUI.getOpaqueInsets(border, c);
else
insets = c.getInsets();
if (insets != null) {
dx += insets.left;
dy += insets.top;
dw -= (insets.left + insets.right);
dh -= (insets.top + insets.bottom);
}
if (toolbar)
//此状态下JToggleButton和JButton使用各自的背景实现2012-10-16前无论是不是JToggleButton都是使用该种实是不太合理的
if (model.isRollover() || model.isPressed())
if (c instanceof JToggleButton)
BEToggleButtonUI.ICON_9.get("rollover").draw((Graphics2D) g, dx, dy, dw, dh);
else
ICON_9.get("pressed").draw((Graphics2D) g, dx, dy, dw, dh);
else if (model.isSelected())
BEToggleButtonUI.ICON_9.get("selected").draw((Graphics2D) g, dx, dy, dw, dh);
else {
//TODO 其它状态下的按钮背景样式需要完善要不然看起来太硬
// skin.paintSkin(g, dx, dy, dw, dh, state);
}
else {
//TODO 其它状态下的按钮背景样式需要完善要不然看起来太硬
String key;
if (model.isArmed() && model.isPressed() || model.isSelected())
key = "pressed";
else if (!model.isEnabled())
key = "disabled";
else if (model.isRollover())
key = "rollover";
else
key = "normal";
ICON_9.get(key).draw((Graphics2D) g, dx, dy, dw, dh);
}
}
}
/**
* returns - b.getBorderInsets(c) if border is opaque - null if border is
* completely non-opaque - somewhere inbetween if border is compound and
* outside border is opaque and inside isn't
*
* @param b the b
* @param c the c
* @return the opaque insets
*/
private static Insets getOpaqueInsets(Border b, Component c) {
if (b == null)
return null;
if (b.isBorderOpaque())
return b.getBorderInsets(c);
else if (b instanceof CompoundBorder) {
CompoundBorder cb = (CompoundBorder) b;
Insets iOut = getOpaqueInsets(cb.getOutsideBorder(), c);
if (iOut != null && iOut.equals(cb.getOutsideBorder().getBorderInsets(c))) {
// Outside border is opaque, keep looking
Insets iIn = getOpaqueInsets(cb.getInsideBorder(), c);
if (iIn == null)
// Inside is non-opaque, use outside insets
return iOut;
else
// Found non-opaque somewhere in the inside (which is
// also compound).
return new Insets(iOut.top + iIn.top, iOut.left + iIn.left,
iOut.bottom + iIn.bottom, iOut.right + iIn.right);
} else
// Outside is either all non-opaque or has non-opaque
// border inside another compound border
return iOut;
} else
return null;
}
public static class BEEmptyBorder extends EmptyBorder implements UIResource {
public BEEmptyBorder(Insets m) {
super(m.top + 2, m.left + 2, m.bottom + 2, m.right + 2);
}
@Override
public Insets getBorderInsets(Component c) {
return getBorderInsets(c, getBorderInsets());
}
@Override
public Insets getBorderInsets(Component c, Insets insets) {
insets = super.getBorderInsets(c, insets);
Insets margin = null;
if (c instanceof AbstractButton) {
Insets m = ((AbstractButton) c).getMargin();
// if this is a toolbar button then ignore getMargin()
// and subtract the padding added by the constructor
if (c.getParent() instanceof JToolBar
&& !(c instanceof JRadioButton)
&& !(c instanceof JCheckBox)
&& m instanceof InsetsUIResource) {
insets.top -= 2;
insets.left -= 2;
insets.bottom -= 2;
insets.right -= 2;
} else
margin = m;
} else if (c instanceof JToolBar)
margin = ((JToolBar) c).getMargin();
else if (c instanceof JTextComponent)
margin = ((JTextComponent) c).getMargin();
if (margin != null) {
insets.top = margin.top + 2;
insets.left = margin.left + 2;
insets.bottom = margin.bottom + 2;
insets.right = margin.right + 2;
}
return insets;
}
}
}

View File

@ -0,0 +1,125 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEToggleButtonUI.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.button;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicToggleButtonUI;
import org.jackhuang.hmcl.laf.BEUtils;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
import org.jackhuang.hmcl.laf.utils.MySwingUtilities2;
/**
* JToggleButton的UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
* @see com.sun.java.swing.plaf.windows.WindowsToggleButtonUI
*/
public class BEToggleButtonUI extends BasicToggleButtonUI {
protected static final Icon9Factory ICON_9 = new Icon9Factory("toggle_button");
private static final BEToggleButtonUI INSTANCE = new BEToggleButtonUI();
public static ComponentUI createUI(JComponent b) {
return INSTANCE;
}
//* 由Jack Jiang于2012-10-12日加入重写本方法的目的是使得JToggleButton不填充
//* BasicToggleButtonUI里的白色距形区否则在JToolBar上时会因该白色距形区的存
//* 在而使得与BEToolBarUI的渐变背景不协调丑陋的创可贴效果实际上
//* WindowsToolButtonUI里有同名方法里也是它样处理的详情参见WindowsToolButtonUI
@Override
protected void installDefaults(AbstractButton b) {
super.installDefaults(b);
LookAndFeel.installProperty(b, "opaque", Boolean.FALSE);
}
// ********************************
// Paint Methods
// ********************************
@Override
public void paint(Graphics g, JComponent c) {
BEButtonUI.paintXPButtonBackground(g, c);
super.paint(g, c);
}
//修改的目的是让它在获得焦点或说点中时改变前景色可惜父类中没有实现它只能自已来解决了
/**
* As of Java 2 platform v 1.4 this method should not be used or overriden.
* Use the paintText method which takes the AbstractButton argument.
*
* @param g the g
* @param c the c
* @param textRect the text rect
* @param text the text
* @see
* javax.swing.plaf.basic.BasicToggleButtonUI#paintText(java.awt.Graphics,
* javax.swing.JComponent, java.awt.Rectangle, java.lang.String)
*/
@Override
protected void paintText(Graphics g, JComponent c, Rectangle textRect, String text) {
AbstractButton b = (AbstractButton) c;
ButtonModel model = b.getModel();
FontMetrics fm = MySwingUtilities2.getFontMetrics(c, g);
int mnemonicIndex = b.getDisplayedMnemonicIndex();
if (model.isEnabled()) {
if (model.isSelected())
g.setColor(UIManager.getColor(getPropertyPrefix() + "focus"));
else
g.setColor(b.getForeground());
MySwingUtilities2.drawStringUnderlineCharAt(c, g, text, mnemonicIndex,
textRect.x + getTextShiftOffset(),
textRect.y + fm.getAscent() + getTextShiftOffset());
} else {
g.setColor(b.getBackground().brighter());
MySwingUtilities2.drawStringUnderlineCharAt(c, g, text, mnemonicIndex,
textRect.x, textRect.y + fm.getAscent());
g.setColor(b.getBackground().darker());
MySwingUtilities2.drawStringUnderlineCharAt(c, g, text, mnemonicIndex,
textRect.x - 1, textRect.y + fm.getAscent() - 1);
}
}
/**
* {@inheritDoc}
*
* Method signature defined here overriden in subclasses. Perhaps this class
* should be abstract?
*/
@Override
protected void paintFocus(Graphics g, AbstractButton b,
Rectangle viewRect, Rectangle textRect, Rectangle iconRect) {
Rectangle bound = b.getVisibleRect();
//决定焦点要制的位置当前实现是往内缩3个像素与当前按钮背景配合
final int delta = 3;
int x = bound.x + delta, y = bound.y + delta, w = bound.width - delta * 2, h = bound.height - delta * 2;
//绘制焦点虚线框
g.setColor(UIManager.getColor("ToggleButton.focusLine"));//*~ 这是Jack Jiang自定义的属性哦
BEUtils.drawDashedRect(g, x, y, w, h, 17, 17, 2, 2);
//再绘制焦点虚线框的立体高亮阴影以便形成立体感
g.setColor(UIManager.getColor("ToggleButton.focusLineHilight"));//*~ 这是Jack Jiang自定义的属性哦
BEUtils.drawDashedRect(g, x + 1, y + 1, w, h, 17, 17, 2, 2);
}
}

View File

@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program.
*/
package org.jackhuang.hmcl.laf;
package org.jackhuang.hmcl.laf.button;
import java.awt.Color;
import org.jackhuang.hmcl.util.ui.GraphicsUtils;
@ -23,7 +23,7 @@ import org.jackhuang.hmcl.util.ui.GraphicsUtils;
*
* @author huangyuhui
*/
public class ConstomButton extends javax.swing.JButton {
public class CustomButton extends javax.swing.JButton {
public Color normalFg = GraphicsUtils.getWebColorWithAlpha("DDDDDD6F"), normalBg = GraphicsUtils.getWebColorWithAlpha("DDDDDD6F"),
prelightFg = GraphicsUtils.getWebColorWithAlpha("FFFFFF7F"), prelightBg = GraphicsUtils.getWebColorWithAlpha("FFFFFF7F"),
activeFg = GraphicsUtils.getWebColorWithAlpha("EAEDF83F"), activeBg = GraphicsUtils.getWebColorWithAlpha("EAEDF83F");

View File

@ -0,0 +1,140 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.laf.button;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.RoundRectangle2D;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.Timer;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicButtonUI;
import org.jackhuang.hmcl.util.ui.GraphicsUtils;
import org.jackhuang.hmcl.laf.button.BEButtonUI;
/**
*
* @author huang
*/
public class CustomButtonUI extends BasicButtonUI {
private static final String DEFAULT_NORMAL = "D5D5D5";
private static final Color[] DEFAULT_NORMAL_FG = new Color[] {
GraphicsUtils.getWebColor(DEFAULT_NORMAL),
GraphicsUtils.getWebColor(DEFAULT_NORMAL)
};
private static final String DEFAULT_PRELIGHT = "A9A9A9";
private static final Color[] DEFAULT_PRELIGHT_FG = new Color[] {
GraphicsUtils.getWebColor(DEFAULT_PRELIGHT),
GraphicsUtils.getWebColor(DEFAULT_PRELIGHT)
};
private static final String DEFAULT_ACTIVE = "222222";
private static final Color[] DEFAULT_ACTIVE_FG = new Color[] {
GraphicsUtils.getWebColor(DEFAULT_ACTIVE),
GraphicsUtils.getWebColor(DEFAULT_ACTIVE)
};
private static final Color[] DISABLED_BG = new Color[] {
GraphicsUtils.getWebColor("E3EFE9"),
GraphicsUtils.getMidWebColor("E3EFE9", "DFE2E6"),
GraphicsUtils.getWebColor("DFE2E6"),
GraphicsUtils.getMidWebColor("DFE2E6", "D6D9DF"),
GraphicsUtils.getWebColor("D6D9DF"),
GraphicsUtils.getWebColor("D6D9DF"),
GraphicsUtils.getMidWebColor("D6D9DF", "D8DBE1"),
GraphicsUtils.getWebColor("D8DBE1"),
GraphicsUtils.getWebColor("DADDE3")
};
private static final Color[] DISABLED_FG = new Color[] {
GraphicsUtils.getWebColor("C9CCD2"),
GraphicsUtils.getWebColor("C9CCD2"),
GraphicsUtils.getWebColor("BCBFC5"),
GraphicsUtils.getWebColor("BCBFC5")
};
private static boolean processCustomButton(final CustomButton c, int add) {
if (c.drawPercent == 0 || c.drawPercent == 100) {
Timer t = new Timer(1, null);
t.addActionListener(x -> {
c.drawPercent += add;
if (c.drawPercent > 100 && add > 0) {
c.drawPercent = 100;
t.stop();
} else if (c.drawPercent < 0 && add < 0) {
c.drawPercent = 0;
t.stop();
} else
c.updateUI();
});
t.start();
}
return true;
}
@Override
protected void installDefaults(AbstractButton b) {
super.installDefaults(b);
LookAndFeel.installProperty(b, "opaque", Boolean.FALSE);
}
@Override
public void paint(Graphics g, JComponent component) {
CustomButton c = (CustomButton) component;
ButtonModel model = c.getModel();
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color[] fg, bg;
if (model.isPressed()) {
fg = new Color[] { c.activeFg, c.activeFg };
bg = new Color[] { c.activeFg, c.activeFg };
} else if (!c.isEnabled())
return;
else if (model.isRollover()) {
if (!processCustomButton(c, 1))
return;
Color fgs = GraphicsUtils.getMidWebColor(c.normalFg, c.prelightFg, c.drawPercent);
Color bgs = GraphicsUtils.getMidWebColor(c.normalBg, c.prelightBg, c.drawPercent);
fg = new Color[] { fgs, fgs };
bg = new Color[] { bgs, bgs };
} else {
if (!processCustomButton(c, -1))
return;
Color fgs = GraphicsUtils.getMidWebColor(c.normalFg, c.prelightFg, c.drawPercent);
Color bgs = GraphicsUtils.getMidWebColor(c.normalBg, c.prelightBg, c.drawPercent);
fg = new Color[] { fgs, fgs };
bg = new Color[] { bgs, bgs };
}
int radix = c.radix;
int x = 0, y = 0, w = c.getWidth(), h = c.getHeight();
g2.setColor(fg[0]);
RoundRectangle2D fgshape = new RoundRectangle2D.Float(x, y, w, h, radix, radix);
g2.draw(fgshape);
g2.setColor(bg[0]);
RoundRectangle2D bgshape = new RoundRectangle2D.Float(x, y, w, h, radix, radix);
g2.fill(bgshape);
super.paint(g, c);
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.button;
import java.awt.Insets;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicBorders.MarginBorder;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
public static void uiImpl() {
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JButton相关ui属性设定
put("Button.background", BeautyEyeLNFHelper.commonBackgroundColor);
//Button.foreground的设定不起效这可能是LNF里的bug因NLLookAndFeel
//是继承自它们所以暂时无能为力就这么的吧以后再说
put("Button.foreground", BeautyEyeLNFHelper.commonForegroundColor);
//以下属性将决定按钮获得焦点时的焦点虚线框的绘制偏移量哦
put("Button.dashedRectGapX", 3);
put("Button.dashedRectGapY", 3);
put("Button.dashedRectGapWidth", 6);
put("Button.dashedRectGapHeight", 6);
put("ButtonUI", BEButtonUI.class);
putInsets("Button.margin", 2, 5, 2, 5);
//此border可以与Button.margin连合使用而者之和即查整个Button的内衬哦
UIManager.put("Button.border", new BEButtonUI.BEEmptyBorder(new Insets(3, 3, 3, 3)));
//获得焦点时的虚线框颜色
putColor("Button.focus", 130, 130, 130);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JToggleButton相关ui属性设定
//注意本属性不要与ToggleButton.border混用因为没有它的优先级高
//另本参数如用InsetsUIResource则不会有效果具体原因待查本属性也将决定toolbar的整体高度和宽度哦
putInsets("ToggleButton.margin", 3, 11, 3, 11);//4, 8, 4, 8));////4, 12, 4, 12));
put("ToggleButton.background", BeautyEyeLNFHelper.commonBackgroundColor);
put("ToggleButton.foreground", BeautyEyeLNFHelper.commonForegroundColor);
//用于ToggleButon被选中时的前景色
//在原WindowsLookAndFeel中本属性存在值是Color(0,0,0,)但在UI里没有用到
//此处被jb2011定义为选中时的前景色当然也可以自已定名称参见 NLWindowsToggleButtonUI2.paintText(..)
put("ToggleButton.focus", BeautyEyeLNFHelper.commonForegroundColor);// Color.white
put("ToggleButtonUI", BEToggleButtonUI.class);
//以下设置对ToggleButton在不加入到JToolBar时是有效果的哦
// UIManager.put("ToggleButton.margin",new InsetsUIResource(2, 30, 2, 30));
put("ToggleButton.border", new MarginBorder());
/* ~~注这个属性是Jack Jiang为了更好的ui效果自已加的属性焦点虚线的颜色 */
put("ToggleButton.focusLine", BeautyEyeLNFHelper.commonFocusedBorderColor.darker());
/* ~~注这个属性是Jack Jiang为了更好的ui效果自已加的属性焦点虚线的高亮立体阴影颜色 */
putColor("ToggleButton.focusLineHilight", 240, 240, 240);
}
}

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEComboBoxRenderer.java at 2015-2-1 20:25:38, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.combox;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JList;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
import org.jackhuang.hmcl.laf.menu.BEMenuUI;
import org.jackhuang.hmcl.laf.BEUtils;
/**
* JComboBox组件下拉选项的render默认实现类.
*
* @author Jack Jiang(jb2011@163.com), 2012-07-05
* @see BEComboBoxUI
*/
public class BEComboBoxRenderer extends BasicComboBoxRenderer {
/**
* 当前下拉框里的item是否被选中用于是否要将背景填充选中样式时使用.
*/
private boolean selected = false;
/**
* 记下本render对应的JComboBox的UI.
*/
private BEComboBoxUI comboBoxUI = null;
public BEComboBoxRenderer(BEComboBoxUI ui) {
super();
this.comboBoxUI = ui;
//设置成透明背景则意味着不需要背景填充但本类中的应用场景有点特殊
//默认的render的UI里不需要绘制背景的情况下本类才可进行NinePatch图作为背景进行填充
setOpaque(false);
//TODO 此borderrender的内衬可以作为一个UIManager的属性哦方便以后设置
//此内衬是决定列表单元间的上下左右空白的关键哦
setBorder(BorderFactory.createEmptyBorder(5, 4, 5, 8));//此设置是与Combox.border UI属性配合哦
}
/**
* {@inheritDoc}
*
* @see
* javax.swing.plaf.basic.BasicComboBoxRenderer#getListCellRendererComponent
* (javax.swing.JList, java.lang.Object, int, boolean, boolean)
*/
@Override
public Component getListCellRendererComponent(JList list,
Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list,
value, index, isSelected, cellHasFocus);
//add by jb2011保存选中状态
this.selected = isSelected;
return c;
}
/**
* {@inheritDoc}
*
* 按理说本方法中的是否选中背景填充实现逻辑在Render的UI中实现最为合理但由于
* 本类就是处理于UI实现中所以容易产生冲突故而不适宜自定义Ui实现干脆硬编码则更直接
*/
@Override
public void paintComponent(Graphics g) {
//当下拉选项弹出时 该item是被选中时才需要把背景填充成选中样式
if (comboBoxUI.isPopupVisible(null) && selected)
BEMenuUI.drawSelectedBackground(g, 0, 0, this.getWidth(), this.getHeight());
//下拉选项未弹出时JComboBox的背景样式
//按理说本类已设置成透明而无须填充背景但本应用场景中只能在默认Ui不填充背景的情况下才
//能完成自定义NinePatch背景的填充 ComponentUI.update(Graphics g, JComponent c)方法
//注意本组件已经被设置成opaque=false即透明否则本方法还会填充默认背景那么选中时的
//N9图背景因先绘将会被覆盖哦所以要使用N9图作为选中时的背景则前提是本组件必须是透明
super.paintComponent(g);
}
//copy from BasicComboBoxRenderer and modified by jb2011
/**
* A subclass of BasicComboBoxRenderer that implements UIResource.
* BasicComboBoxRenderer doesn't implement UIResource directly so that
* applications can safely override the cellRenderer property with
* BasicListCellRenderer subclasses.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with future Swing
* releases. The current serialization support is appropriate for short term
* storage or RMI between applications running the same version of Swing. As
* of 1.4, support for long term storage of all
* JavaBeans<sup><font size="-2">TM</font></sup>
* has been added to the <code>java.beans</code> package. Please see
* {@link java.beans.XMLEncoder}.
*/
public static class UIResource extends BEComboBoxRenderer implements javax.swing.plaf.UIResource {
/**
* Instantiates a new uI resource.
*
* @param ui the ui
*/
public UIResource(BEComboBoxUI ui) {
super(ui);
}
}
}

View File

@ -0,0 +1,362 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEComboBoxUI.java at 2015-2-1 20:25:38, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.combox;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ComboBoxEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import javax.swing.plaf.basic.BasicComboBoxUI;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
/**
* JComboBox的UI实现类.
*
* @author Jack Jiang(jb2011@163.com), 2012-06-30
* @version 1.0
* @see com.sun.java.swing.plaf.windows.WindowsComboBoxUI
*/
public class BEComboBoxUI extends BasicComboBoxUI
implements org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported, MouseListener {
private static final Icon9Factory ICON_9 = new Icon9Factory("combo");
private static final Dimension BTN_SIZE = new Dimension(17, 20);
private final Dimension btnSize = new Dimension(BTN_SIZE);
public static ComponentUI createUI(JComponent c) {
return new BEComboBoxUI();
}
//* 本方法由Jack Jiang于2012-09-07日加入
/**
* 是否使用父类的绘制实现方法true表示是.
* <p>
* 因为在BE LNF中边框和背景等都是使用N9图没法通过设置背景色和前景
* 色来控制JComboBox的颜色和边框本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE
* LNF中默认的N9图填充绘制而改用父类中的方法父类中的方法 就可以支持颜色的设置罗只是丑点但总归是能适应用户的需求场景要求其实用户完全可以
* 通过JComboBox.setUI(..)方式来自定义UI哦.
*
* @return true, if is use parent paint
*/
@Override
public boolean isUseParentPaint() {
return comboBox != null
&& (!(comboBox.getBorder() instanceof UIResource)
|| !(comboBox.getBackground() instanceof UIResource));
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
//2012-08-30*******************************************************重要说明 START 对应BEListUI中的重要说明
//* 重要说明因BEListUI中为了使列表行单元高变的更高在MyDefaultListCellRenderer.java中
//* 像COmboxRender一样通过增到border不起效果它可能是BasicListUI的设计缺陷它要么取FixedCellHeight
//* 固定值要么取getPreferSize()即自动计算高度它似乎是不计入border的所以render设置border不起效
//* 所以只能为列表单元设置因定值list.setFixedCellHeight(30)但它将影响Combox里的行高也会变成30高
//* 所以此处要把列表UI中强制设定的30高针对Combox还原成自动计算API中规定FixedCellHeight==-1即表示自动计算
popup.getList().setFixedCellHeight(-1);
//**************************************************************** 重要说明 END
//* 以下代码由jb2011加入
// comboBox.setMaximumRowCount(8);//这个最大行可以起效但似乎它的行高指的是一个固定值而不是计算值像本LNF里因cell本身行高就很高
//即使设置了最大显示行但是显示的并不是指定值有待进一步研究
//为下拉框的弹出弹加border这样上下空白外一点好看一些
// install the scrollpane border
Container parent = popup.getList().getParent(); // should be viewport
if (parent != null) {
parent = parent.getParent(); // should be the scrollpane
if (parent != null && parent instanceof JScrollPane)
LookAndFeel.installBorder((JScrollPane) parent, "ComboBox.scrollPaneBorder");//*~ 这个属性是Jack Jiang仿照JTabel里的实现自已加的属性
}
}
@Override
protected void installListeners() {
super.installListeners();
comboBox.addMouseListener(this);
}
@Override
protected void uninstallListeners() {
super.uninstallListeners();
comboBox.removeMouseListener(this);
}
/**
* Gets the combox.
*
* @return the combox
*/
public JComboBox getCombox() {
return this.comboBox;
}
/**
* {@inheritDoc}
*
* 自定义下接框箭头按钮实现类
*/
@Override
protected JButton createArrowButton() {
JButton button = new JButton() {
@Override
protected void paintComponent(Graphics g) {
if (comboBox.isEditable())
ICON_9.getWithComboState("", comboBox.isEnabled(), mouseDown, mouseInside)
.draw((Graphics2D) g, 0, 0, getWidth(), getHeight());
}
};
button.addMouseListener(this);
button.setMinimumSize(BTN_SIZE);
button.setPreferredSize(BTN_SIZE);
button.setMargin(new Insets(0, 0, 0, 0));
return button;
}
@Override
public void paint(Graphics g, JComponent c) {
hasFocus = comboBox.hasFocus();
ListCellRenderer renderer = comboBox.getRenderer();
Rectangle r = new Rectangle(0, 0, comboBox.getWidth(), comboBox.getHeight());
paintCurrentValueBackground(g, r, hasFocus);
if (!comboBox.isEditable())
paintCurrentValue(g, rectangleForCurrentValue(), false);
}
/**
* Paints the background of the currently selected item.
*
* @param g the g
* @param bounds the bounds
* @param hasFocus the has focus
* @see javax.swing.plaf.basic.BasicComboBoxUI#paintCurrentValueBackground(java.awt.Graphics, java.awt.Rectangle, boolean)
*/
@Override
public void paintCurrentValueBackground(Graphics g, Rectangle bounds, boolean hasFocus) {
ICON_9.getWithComboState("", comboBox.isEnabled(), mouseDown, mouseInside)
.draw((Graphics2D) g, bounds.x, bounds.y, bounds.width, bounds.height);
}
//* copy from BasicComboBoxUI and modified by jb2011
/**
* Creates the default renderer that will be used in a non-editiable combo
* box. A default renderer will used only if a renderer has not been
* explicitly set with <code>setRenderer</code>.
*
* @return a <code>ListCellRender</code> used for the combo box
* @see javax.swing.JComboBox#setRenderer
*/
@Override
protected ListCellRenderer createRenderer() {
return new BEComboBoxRenderer.UIResource(this);
}
/**
* {@inheritDoc}
*
* 改变方法可见性
*/
@Override
public Insets getInsets() {
return super.getInsets();
}
/**
* Creates the popup portion of the combo box.
*
* 目的是修正弹出popup窗口的xy坐标不像菜单UI里有
* Menu.menuPopupOffsetX等4个属性可设置以备对坐标进行调整BeautyEye LNF中由Jack Jiang
* 依照Menu中的实现自定义了2个属性以便以后配置参考自jdk1.6.0_u18源码.
*
* @return an instance of <code>ComboPopup</code>
* @see javax.swing.plaf.basic.BasicComboBoxUI#createPopup()
*/
@Override
protected ComboPopup createPopup() {
return new BasicComboPopup(comboBox) {
/**
* popupOffsetX是jb2011自定的属性用于修正下拉框的弹出窗的X坐标
*/
private final int popupOffsetX = UIManager.getInt("ComboBox.popupOffsetX");
/**
* popupOffsetY是jb2011自定的属性用于修正下拉框的弹出窗的Y坐标
*/
private final int popupOffsetY = UIManager.getInt("ComboBox.popupOffsetY");
@Override
public void show() {
setListSelection(comboBox.getSelectedIndex());
Point location = getPopupLocation();
show(comboBox, //以下xy坐标修正代码由Jack Jiang增加
location.x + popupOffsetX, //*~ popupOffsetX是自定属性用于修改弹出窗的X坐标
location.y + popupOffsetY //*~ popupOffsetY是自定属性用于修改弹出窗的Y坐标
);
}
/**
* Sets the list selection index to the selectedIndex. This method
* is used to synchronize the list selection with the combo box
* selection.
*
* @param selectedIndex the index to set the list
* @see javax.swing.plaf.basic.BasicComboPopup#setListSelection(int)
*/
private void setListSelection(int selectedIndex) {
if (selectedIndex == -1)
list.clearSelection();
else {
list.setSelectedIndex(selectedIndex);
list.ensureIndexIsVisible(selectedIndex);
}
}
/**
* Calculates the upper left location of the Popup.
*
* @see javax.swing.plaf.basic.BasicComboPopup#getPopupLocation()
*/
private Point getPopupLocation() {
Dimension popupSize = comboBox.getSize();
Insets insets = getInsets();
// reduce the width of the scrollpane by the insets so that the popup
// is the same width as the combo box.
popupSize.setSize(popupSize.width - (insets.right + insets.left),
getPopupHeightForRowCount(comboBox.getMaximumRowCount()));
Rectangle popupBounds = computePopupBounds(0, comboBox.getBounds().height,
popupSize.width, popupSize.height);
Dimension scrollSize = popupBounds.getSize();
Point popupLocation = popupBounds.getLocation();
scroller.setMaximumSize(scrollSize);
scroller.setPreferredSize(scrollSize);
scroller.setMinimumSize(scrollSize);
list.revalidate();
return popupLocation;
}
};
}
/**
* Creates the default editor that will be used in editable combo boxes. A
* default editor will be used only if an editor has not been explicitly set
* with <code>setEditor</code>.
*
* 重写父类方法的目的是使得默认的
* Editor透明即不填充默认背景因为BE LNF中JTextField的LNF是用NP图
* 实现的此处不透明的话就会遮住NP背景图从而使得外观难看
*
* Fixed Issue 49(https://code.google.com/p/beautyeye/issues/detail?id=49)
*
* @return a <code>ComboBoxEditor</code> used for the combo box
* @see javax.swing.JComboBox#setEditor
* @see com.sun.java.swing.plaf.windows.WindowsComboBoxUI.WindowsComboBoxEditor
*/
@Override
protected ComboBoxEditor createEditor() {
BasicComboBoxEditor.UIResource bcbe = new BasicComboBoxEditor.UIResource();
Component c = bcbe.getEditorComponent();
if (c != null) {
//把默认的Editor设置成透明(editor不透明的话就会遮住NP背景图从而使得外观难看)
((JComponent) c).setOpaque(false);
//* 以下这段是为了给默认Editor加上border而加没有它个border将使
//* 得与不可编辑comboBox的内容组件看起来有差异哦
//* 在WindowsComboBoxUI中这段代码是放在WindowsComboBoxEditor
//* 中的方法createEditorComponent中实现由于该 方法是1.6里才有的
//* BE LNF因要兼容java1.5所以不作类似实现就在本方法中实现也没有问题
//* 类似实现请参考WindowsComboBoxUI.WindowsComboBoxEditor类
// JTextField editor = (JTextField)c;
Border border = (Border) UIManager.get("ComboBox.editorBorder");
if (border != null)
((JComponent) c).setBorder(border);
}
return bcbe;
}
// =================================================================================================================
// MouseListener Methods
private boolean mouseInside = false;
private boolean mouseDown = false;
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
if (comboBox.isEditable()) {
if (e.getComponent() == arrowButton)
mouseInside = true;
} else {
mouseInside = true;
comboBox.repaint();
}
}
@Override
public void mouseExited(MouseEvent e) {
if (comboBox.isEditable()) {
if (e.getComponent() == arrowButton)
mouseInside = false;
} else {
mouseInside = false;
comboBox.repaint();
}
}
@Override
public void mousePressed(MouseEvent e) {
if (comboBox.isEditable()) {
if (e.getComponent() == arrowButton)
mouseDown = true;
} else {
mouseDown = true;
comboBox.repaint();
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (comboBox.isEditable()) {
if (e.getComponent() == arrowButton)
mouseDown = false;
} else {
mouseDown = false;
comboBox.repaint();
}
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:37, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.combox;
import java.awt.Color;
import javax.swing.UIManager;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
public static void uiImpl() {
/* ~~注这个属性是Jack Jiang仿照JTabel里的实现自已加的属性目的是控制选择框的弹出列表的边框空白 */
putBorder("ComboBox.scrollPaneBorder", 0, 0, 0, 0);
// 不能设置alpha通道小于255的透明颜色否则会出现无法重paint的问题
putColor("ComboBox.background", 242, 242, 242);
put("ComboBox.disabledBackground", BeautyEyeLNFHelper.commonBackgroundColor);
// put("ComboBox.buttonBackground", BeautyEyeLNFHelper.commonBackgroundColor);
putColor("ComboBox.buttonBackground", 242, 242, 242);
put("ComboBox.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor);
put("ComboBox.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
put("ComboBox.foreground", BeautyEyeLNFHelper.commonForegroundColor);
//render之外的衬距此设置将改变下拉框的整体占位大小
putInsets("ComboBox.padding", 0, 0, 0, 0);//5,8,5,8));
//true表示下拉箭头按钮的宽度无条件=高度否则宽度不与高度保持等长使用自身长度
UIManager.put("ComboBox.squareButton", true);
//此border将决定ArrowButton的外衬大小即框内衬空白大小此大小决定conbox的高度和宽度另一种方法
//是通过设置render的border也能达到调整combox的高度和宽度而且对lnf来说通过设置render的border是最佳方案
putBorder("ComboBox.border", 0, 4, 0, 0);//new BERoundBorder(0).setThickness(10)));//.setArcWidth(10).setLineColor(new Color(0,0,0,0))));//使用全透明色绘边框目的就是要让它的背景显现出来NipePatch图实现
putBorder("ComboBox.editorBorder", 0, 4, 0, 0);//windows 外观下认是1,2,1,1)));
put("ComboBoxUI", BEComboBoxUI.class);
/* ~~注这个属性是Jack Jiang为了更好的ui效果和方便未来的设定自已加的属性 */
//用于修正下拉框的弹出窗的X坐标
put("ComboBox.popupOffsetX", 0);
/* ~~注这个属性是Jack Jiang为了更好的ui效果和方便未来的设定自已加的属性 */
//用于修正下拉框的弹出窗的Y坐标
put("ComboBox.popupOffsetY", 0);
}
}

View File

@ -0,0 +1,149 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEFileChooserUI.java at 2015-2-1 20:25:39, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.filechooser;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.metal.MetalFileChooserUI;
/**
* BeautyEye L&F implementation of a FileChooser.
* <p>
* 目前属通用跨平台专用UI实现类.
*
* @author Jack Jiang(jb2011@163.com), 2012-09-17
* @version 1.0
*/
public class BEFileChooserUI extends MetalFileChooserUI {
public BEFileChooserUI(JFileChooser filechooser) {
super(filechooser);
}
//
// ComponentUI Interface Implementation methods
//
public static ComponentUI createUI(JComponent c) {
return new BEFileChooserUI((JFileChooser) c);
}
/**
* {@inheritDoc}
*
* 目前仅发现Windows平台的WindowsFileChooserUI存在它个问题 本方法由Jack
* Jiang实现没有以下默认背景绘制则在BE LNF中因透明窗口而使得
* 文件选择框内容面板的空白处出现全透明现的丑陋现象注释掉本方法即可见之前的问题
*/
@Override
public void paint(Graphics g, JComponent c) {
g.setColor(c.getBackground());
g.fillRect(0, 0, c.getWidth(), c.getHeight());
}
/**
* 重写父类方法以实现对文件查看列表的额外设置.
* <p>
* 为什么要重写此方法没有更好的方法吗<br>
* 因父类的封装结构不佳filePane是private私有子类中无法直接引用
* 要想对filePane中的文列表额外设置目前重写本方法是个没有办法的方法.
* <p>
* sun.swing.FilePane源码可查看地址<a href="http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/swing/FilePane.java">Click
* here.</a>
*
* @param fc the fc
* @return the j panel
*/
@Override
protected JPanel createList(JFileChooser fc) {
JPanel p = super.createList(fc);
//* 以下代码的作用就是将文件列表JList对象引用给找回来通过从它的父面板中层层向下搜索
//* 因无法从父类中直接获得列表对象的直接引用只能用此笨办法了
if (p.getComponentCount() > 0) {
Component scollPane = p.getComponent(0);
if (scollPane != null && scollPane instanceof JScrollPane) {
JViewport vp = ((JScrollPane) scollPane).getViewport();
if (vp != null) {
Component fileListView = vp.getView();
//终于找到了文件列表的实例引用
if (fileListView != null && fileListView instanceof JList)
//把列表的行高改成-1即自动计算列表每个单元的行高而不指定固定值
//* 说明在BeautyEye LNF中为了便JList的UI更好看在没有其它方法有前
//* 提下就在JList的BEListUI中给它设置了默写行高32而JFildChooser中的
//* 文件列表将会因此而使得单元行高很大从而导致文件列表很难看此处就是恢复
//* 文件列表单元行高的自动计算而非指定固定行高
//*
//* 说明2为什么不能利用list.getClientProperty("List.isFileList")从而在JList
//* 的ui中进行判断并区别对待是否是文件列表呢
//* 因为"List.isFileList"是在BasicFileChooserUI中设置的也就是说当为个属性被
//* 设置的时候JFileChooser中的文件列表已经实例化完成包括它的ui初始化所以此时
//* 如果在JList的ui中想区分是不可能的因它还没有被调置这个设置主要是供BasicListUI
//* 在被实例化完成后来异步处理这个属性的通过监听属性改变事件来实现的
((JList) fileListView).setFixedCellHeight(-1);
}
}
}
return p;
}
// //
// // Renderer for Types ComboBox
// //
// protected FilterComboBoxRenderer createFilterComboBoxRenderer()
// {
// return new BEFilterComboBoxRenderer();
// }
// /**
// * Render different type sizes and styles.
// */
// protected class BEFilterComboBoxRenderer extends FilterComboBoxRenderer
// {
// public BEFilterComboBoxRenderer()
// {
// super();
//
//// //设置成透明背景则意味着不需要背景填充但本类中的应用场景有点特殊
//// //默认的render的UI里不需要绘制背景的情况下本类才可进行NinePatch图作为背景进行填充
//// setOpaque(false);
// //TODO 此borderrender的内衬可以作为一个UIManager的属性哦方便以后设置
// //此内衬是决定列表单元间的上下左右空白的关键哦
//// setBorder(BorderFactory.createEmptyBorder(5, 8, 5, 8));
// }
//
// //按理说本方法中的是否选中背景填充实现逻辑在Render的UI中实现最为合理但由于
// //本类就是处理于UI实现中所以容易产生冲突故而不适宜自定义Ui实现干脆硬编码则更直接
// public void paintComponent(Graphics g)
// {
// //** 本HACK是为了解决 Issue 30因JFileChooser中的文件类型选择下拉框的render
// //** 即本render是自定义的不是使用的ComboxUI里由BE LNF定义好的render而
// //** 导致的视觉效果不佳的问题
// //##### HACK强行把绘制坐标右移下移以便使得与左边的空折多一点要不然就太难看了
// g.translate(5, 1);
//
// //照常绘制只是之前的坐标被移了一下而已
// super.paintComponent(g);
//
// //##### HACK恢复坐标
// g.translate(-5, -1);
// }
// }
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:38, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.filechooser;
import java.awt.Color;
import javax.swing.UIManager;
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.ColorUIResource;
import org.jackhuang.hmcl.laf.utils.IconFactory;
import org.jackhuang.hmcl.laf.utils.UI;
/**
* The Class __UI__.
*/
public class __UI__ extends UI {
private static final IconFactory ICON = new IconFactory("tree");
public static void uiImpl() {
//文件查看列表的边框实现
put("FileChooser.listViewBorder", new org.jackhuang.hmcl.laf.scroll.ScrollPaneBorder());
//此颜色将决定windows平台下文件选择面板的左边WindowsPlaceBar的背景色
putColor("ToolBar.shadow", 249, 248, 243);
put("FileChooserUI", BEFileChooserUI.class);
UIManager.put("FileView.directoryIcon", ICON.get("closed"));
UIManager.put("FileView.fileIcon", ICON.get("leaf"));
/*
"FileView.directoryIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getTreeFolderIcon"),
"FileView.fileIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getTreeLeafIcon"),
"FileView.computerIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getTreeComputerIcon"),
"FileView.hardDriveIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getTreeHardDriveIcon"),
"FileView.floppyDriveIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getTreeFloppyDriveIcon"),
// File Chooser
"FileChooser.detailsViewIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getFileChooserDetailViewIcon"),
"FileChooser.homeFolderIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getFileChooserHomeFolderIcon"),
"FileChooser.listViewIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getFileChooserListViewIcon"),
"FileChooser.newFolderIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getFileChooserNewFolderIcon"),
"FileChooser.upFolderIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getFileChooserUpFolderIcon"),
*/
}
}

View File

@ -0,0 +1,121 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEDesktopIconUI.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.internalframe;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicDesktopIconUI;
/**
* 内部窗体最小化时的图标ui实现类.
*
* @author Jack Jiang(jb2011@163.com)
* @see com.sun.java.swing.plaf.windows.WindowsDesktopIconUI
*/
public class BEDesktopIconUI extends BasicDesktopIconUI {
private int width;
public static ComponentUI createUI(JComponent c) {
return new BEDesktopIconUI();
}
/**
* {@inheritDoc}
*
* @see com.sun.java.swing.plaf.windows.WindowsDesktopIconUI#installDefaults
*/
@Override
public void installDefaults() {
super.installDefaults();
width = UIManager.getInt("DesktopIcon.width");
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
c.setOpaque(false);
}
/**
* {@inheritDoc}
*
* @see com.sun.java.swing.plaf.windows.WindowsDesktopIconUI#uninstallUI
*/
@Override
public void uninstallUI(JComponent c) {
BEInternalFrameTitlePane thePane = (BEInternalFrameTitlePane) iconPane;
super.uninstallUI(c);
thePane.uninstallListeners();
}
@Override
protected void installComponents() {
iconPane = new BEInternalFrameTitlePane(frame) {
@Override
protected void paintTitlePaneImpl(Insets frameInsets, Graphics g,
int width, int height, boolean isSelected) {
//** Swing BUG补尝重写父类的目的就是想用Insets(0,0,0,0)来调用paintTitlePaneImpl(否则因
//** BasicInternalFrameTitlePane中的布局bug将会导致填充错位)
Insets instes = new Insets(0, 0, 0, 0);
super.paintTitlePaneImpl(instes, g, width, height, isSelected);
}
};
desktopIcon.setLayout(new BorderLayout());
desktopIcon.add(iconPane, BorderLayout.CENTER);
desktopIcon.setBorder(UIManager.getBorder("InternalFrame.border"));
}
/**
* {@inheritDoc}
*
* @see
* com.sun.java.swing.plaf.windows.WindowsDesktopIconUI#getPreferredSize(javax.swing.JComponent)
*/
@Override
public Dimension getPreferredSize(JComponent c) {
// Windows desktop icons can not be resized. Therefore, we should
// always return the minimum size of the desktop icon. See
// getMinimumSize(JComponent c).
return getMinimumSize(c);
}
/**
* Windows desktop icons are restricted to a width of 160 pixels by default.
* This value is retrieved by the DesktopIcon.width property.
*
* @param c the c
* @return the minimum size
* @see
* com.sun.java.swing.plaf.windows.WindowsDesktopIconUI#getPreferredSize(javax.swing.JComponent)
*/
@Override
public Dimension getMinimumSize(JComponent c) {
//## Bug FIXsee Issue 60(https://code.google.com/p/beautyeye/issues/detail?id=60&can=1)
//## bug起源此bug源自WindowsDesktopIconUIBeautyEye因参考了它的实现因而也把该bug带了过来
//## 是否解决已于2012-10-19日由Jack Jiang解决
//## bug描述在某些情况下比如在cpcns的定制be lnf项目中它的内部窗口先最大化后再最小化时该DesptopIcon
//## 的高度就变的较小与正常状态下有差异具体原因待深究
//## 解决方法参考MetalDesktopIconUI里的实现用现在的代码即可解决这个问题
// Dimension dim = super.getMinimumSize(c);
// dim.width = width;
// return dim;
return new Dimension(width,
desktopIcon.getLayout().minimumLayoutSize(desktopIcon).height);
}
}

View File

@ -0,0 +1,631 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEInternalFrameTitlePane.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.internalframe;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.Icon;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
import javax.swing.plaf.metal.MetalLookAndFeel;
import org.jackhuang.hmcl.laf.titlepane.BETitlePane;
import org.jackhuang.hmcl.laf.utils.MySwingUtilities2;
import org.jackhuang.hmcl.laf.utils.WinUtils;
/**
* 内部窗体的标题栏UI实现.
*
* BeautyEye外观实现中取消了isPalette的所有特殊处理isPalette及相关属性在
*该外观中将失去意义请注意
*虽然beautyEye是参考自MetalLookAndFeel但因beautyEye使用了Insets很大的立体边框
* 则如果还要像MetalLookAndFeel实现Palette类型的JInternalFrame则效果会很难看干脆就就像
* WindowsLookAndFeel一样不去理会什么Palette在当前的L&F下没有任何减分
*
* @see com.sun.java.swing.plaf.windows.WindowsInternalFrameTitlePane
* @author Jack Jiang
*/
public class BEInternalFrameTitlePane extends BasicInternalFrameTitlePane {
// protected boolean isPalette = false;
// protected Icon paletteCloseIcon;
// protected int paletteTitleHeight;
/**
* The Constant handyEmptyBorder.
*/
private static final Border handyEmptyBorder = new EmptyBorder(0, 0, 0, 0);
/**
* Key used to lookup Color from UIManager. If this is null,
* <code>getWindowTitleBackground</code> is used.
*/
private String selectedBackgroundKey;
/**
* Key used to lookup Color from UIManager. If this is null,
* <code>getWindowTitleForeground</code> is used.
*/
private String selectedForegroundKey;
/**
* Key used to lookup shadow color from UIManager. If this is null,
* <code>getPrimaryControlDarkShadow</code> is used.
*/
private String selectedShadowKey;
/**
* Boolean indicating the state of the <code>JInternalFrame</code>s closable
* property at <code>updateUI</code> time.
*/
private boolean wasClosable;
/**
* The buttons width.
*/
int buttonsWidth = 0;
/**
* Instantiates a new bE internal frame title pane.
*
* @param f the f
*/
public BEInternalFrameTitlePane(JInternalFrame f) {
super(f);
}
@Override
public void addNotify() {
super.addNotify();
// This is done here instead of in installDefaults as I was worried
// that the BasicInternalFrameUI might not be fully initialized, and
// that if this resets the closable state the BasicInternalFrameUI
// Listeners that get notified might be in an odd/uninitialized state.
updateOptionPaneState();
}
@Override
protected void installDefaults() {
super.installDefaults();
setFont(UIManager.getFont("InternalFrame.titleFont"));
// paletteTitleHeight = UIManager
// .getInt("InternalFrame.paletteTitleHeight");
// paletteCloseIcon = UIManager.getIcon("InternalFrame.paletteCloseIcon");
wasClosable = frame.isClosable();
selectedForegroundKey = selectedBackgroundKey = null;
if (true)
setOpaque(false);
}
@Override
protected void uninstallDefaults() {
super.uninstallDefaults();
if (wasClosable != frame.isClosable())
frame.setClosable(wasClosable);
}
@Override
protected void createButtons() {
super.createButtons();
Boolean paintActive = frame.isSelected() ? Boolean.TRUE : Boolean.FALSE;
iconButton.putClientProperty("paintActive", paintActive);
iconButton.setBorder(handyEmptyBorder);
maxButton.putClientProperty("paintActive", paintActive);
maxButton.setBorder(handyEmptyBorder);
closeButton.putClientProperty("paintActive", paintActive);
closeButton.setBorder(handyEmptyBorder);
// The palette close icon isn't opaque while the regular close icon is.
// This makes sure palette close buttons have the right background.
closeButton.setBackground(MetalLookAndFeel.getPrimaryControlShadow());
if (true) {
iconButton.setContentAreaFilled(false);
maxButton.setContentAreaFilled(false);
closeButton.setContentAreaFilled(false);
}
}
/**
* Override the parent's method to do nothing. Metal frames do not have
* system menus.
*/
@Override
protected void assembleSystemMenu() {
}
/**
* Override the parent's method to do nothing. Metal frames do not have
* system menus.
*
* @param systemMenu the system menu
*/
@Override
protected void addSystemMenuItems(JMenu systemMenu) {
}
/**
* Override the parent's method to do nothing. Metal frames do not have
* system menus.
*/
@Override
protected void showSystemMenu() {
}
/**
* Override the parent's method avoid creating a menu bar. Metal frames do
* not have system menus.
*/
@Override
protected void addSubComponents() {
add(iconButton);
add(maxButton);
add(closeButton);
}
@Override
protected PropertyChangeListener createPropertyChangeListener() {
return new MetalPropertyChangeHandler();
}
@Override
protected LayoutManager createLayout() {
return new XMetalTitlePaneLayout();
}
class MetalPropertyChangeHandler extends
BasicInternalFrameTitlePane.PropertyChangeHandler {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String prop = (String) evt.getPropertyName();
if (prop.equals(JInternalFrame.IS_SELECTED_PROPERTY)) {
Boolean b = (Boolean) evt.getNewValue();
iconButton.putClientProperty("paintActive", b);
closeButton.putClientProperty("paintActive", b);
maxButton.putClientProperty("paintActive", b);
} else if ("JInternalFrame.messageType".equals(prop)) {
updateOptionPaneState();
frame.repaint();
}
super.propertyChange(evt);
}
}
class XMetalTitlePaneLayout extends TitlePaneLayout {
@Override
public void addLayoutComponent(String name, Component c) {
}
@Override
public void removeLayoutComponent(Component c) {
}
@Override
public Dimension preferredLayoutSize(Container c) {
return minimumLayoutSize(c);
}
@Override
public Dimension minimumLayoutSize(Container c) {
// Compute width.
int width = 30;
if (frame.isClosable())
width += 21;
if (frame.isMaximizable())
width += 16 + (frame.isClosable() ? 10 : 4);
if (frame.isIconifiable())
width += 16 + (frame.isMaximizable() ? 2
: (frame.isClosable() ? 10 : 4));
FontMetrics fm = frame.getFontMetrics(getFont());
String frameTitle = frame.getTitle();
int title_w = frameTitle != null ? MySwingUtilities2.stringWidth(
frame, fm, frameTitle) : 0;
int title_length = frameTitle != null ? frameTitle.length() : 0;
if (title_length > 2) {
int subtitle_w = MySwingUtilities2.stringWidth(frame, fm, frame
.getTitle().substring(0, 2)
+ "...");
width += (title_w < subtitle_w) ? title_w : subtitle_w;
} else
width += title_w;
// Compute height.
int height = 0;
// if (isPalette)
// {
// height = paletteTitleHeight;
// }
// else
{
int fontHeight = fm.getHeight();
fontHeight += 4;//默认是 +=7
Icon icon = frame.getFrameIcon();
int iconHeight = 0;
if (icon != null)
// SystemMenuBar forces the icon to be 16x16 or less.
iconHeight = Math.min(icon.getIconHeight(), 16);
iconHeight += 5;
height = Math.max(fontHeight, iconHeight) + 5;//默认是 +0modified by jb2011 2012-06-18
}
return new Dimension(width, height);
}
@Override
public void layoutContainer(Container c) {
boolean leftToRight = WinUtils.isLeftToRight(frame);
int w = getWidth();
int x = leftToRight ? w : 0;
int y = 5;//默认是0modified by jb2011
int spacing;
// assumes all buttons have the same dimensions
// these dimensions include the borders
int buttonHeight = closeButton.getIcon().getIconHeight();
int buttonWidth = closeButton.getIcon().getIconWidth();
if (frame.isClosable()) // if (isPalette)
// {
// spacing = 3;
// x += leftToRight ? -spacing - (buttonWidth + 2) : spacing;
// closeButton.setBounds(x, y, buttonWidth + 2,
// getHeight() - 4);
// if (!leftToRight)
// x += (buttonWidth + 2);
// }
// else
{
spacing = 4;
x += leftToRight ? -spacing - buttonWidth : spacing;
closeButton.setBounds(x, y, buttonWidth, buttonHeight);
if (!leftToRight)
x += buttonWidth;
}
if (frame.isMaximizable())// && !isPalette)
{
spacing = frame.isClosable() ? 2 : 4; //10 : 40
x += leftToRight ? -spacing - buttonWidth : spacing;
maxButton.setBounds(x, y, buttonWidth, buttonHeight);
if (!leftToRight)
x += buttonWidth;
}
if (frame.isIconifiable())// && !isPalette)
{
spacing = frame.isMaximizable() ? 2 : (frame.isClosable() ? 10
: 4);
x += leftToRight ? -spacing - buttonWidth : spacing;
iconButton.setBounds(x, y, buttonWidth, buttonHeight);
if (!leftToRight)
x += buttonWidth;
}
buttonsWidth = leftToRight ? w - x : x;
}
}
// public void paintPalette(Graphics g)
// {
// boolean leftToRight = WinUtils.isLeftToRight(frame);
//
// int width = getWidth();
// int height = getHeight();
//
// Color background = MetalLookAndFeel.getPrimaryControlShadow();
// Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
//
// NLTitlePane.paintTitlePane(g, 0, 0, width , height, false
// , background, darkShadow);
// }
@Override
public void paintComponent(Graphics g) {
// if (isPalette)
// {
// paintPalette(g);
// return;
// }
boolean leftToRight = WinUtils.isLeftToRight(frame);
boolean isSelected = frame.isSelected();//! 选中与否的判断方式参见border部分的注释
int width = getWidth();
int height = getHeight();
Color background = null;
Color foreground = null;
Color shadow = null;
if (isSelected) {
// if (!true)
// {
// closeButton.setContentAreaFilled(true);
// maxButton.setContentAreaFilled(true);
// iconButton.setContentAreaFilled(true);
// }
if (selectedBackgroundKey != null)
background = UIManager.getColor(selectedBackgroundKey);
if (background == null)
background = UIManager.getColor("activeCaption");
if (selectedForegroundKey != null)
foreground = UIManager.getColor(selectedForegroundKey);
if (selectedShadowKey != null)
shadow = UIManager.getColor(selectedShadowKey);
if (shadow == null)
shadow = UIManager.getColor("activeCaptionBorder");
if (foreground == null)
foreground = UIManager.getColor("activeCaptionText");
} else {
if (!true) {
closeButton.setContentAreaFilled(false);
maxButton.setContentAreaFilled(false);
iconButton.setContentAreaFilled(false);
}
background = UIManager.getColor("inactiveCaption");
foreground = UIManager.getColor("inactiveCaptionText");
shadow = UIManager.getColor("inactiveCaptionBorder");
}
//---------------------------------------------------绘制标题栏背景
// Color topDarkShadow2 = LNFUtils.getColor(
// background, -40, -40, -40)
// ,topHightLight2 = LNFUtils.getColor(background,
// 60, 60, 60)
// ,topDarkHightLight2 = LNFUtils.getColor(background,
// 20, 20, 20);
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 绘制标题栏背景START */
/*
* ** bug修正 by js,2009-09-30这因是JDK1.5的Swing底层BUG
*
* BUG描述当操作系统的主题切换时JInternalFrame有时相同的方法this.getBounds()获得的结果是不一样的
* 这种差异主要在于有时this.getBounds()获得的结果并未包括它的border主要表现就是结果
* (x,y)的坐标是未包含border的坐标因而这种情况下它的(x=0,y=0),而正确应该
* (x=border.insets.left,y=border.insets.top)如果无视此bug则titlePane
* 在填充时会变的丑陋
*
* 解决方法当确知这个bug发生后只能以人工方式弥补这种异相 强制修正其(x,y)的坐标并相应地调整
* titlePane的填充区域
*/
// Border b=frame.getBorder();
// Insets is=b.getBorderInsets(frame);
// Rectangle bounds = this.getBounds();
// int paintTitlePaneX = bounds.x,paintTitlePaneY = bounds.y;
//// boolean isBUG = false;
////// System.out.println("JInternalFrame的UI是否处于正常isBUG="+isBUG);
//// if(isBUG=(is.left!=bounds.x))//当is.left!=bounds.x即可认定已经产生了BUG
//// paintTitlePaneX = is.left;
//// if(isBUG=(is.top!=bounds.y))//当is.left!=bounds.x同样可认定已经产生了BUG
//// paintTitlePaneY = is.top;
//// if(isBUG)//有BUG时的填充
//// {
//// //----------------------------- 以下代码是为了弥补因BUG而产生的填充异常
//// //*以下(1),(2),(3)部分代码是用于弥补BUG下的border外观被titlePane覆盖的错误
//// //*请参见JInternalFrameDialogBorder的边框填充代码尽量在此处模拟出边框的TOP部分效果>
//// //水平第一条线(1)
//// g.setColor(topDarkShadow2);
//// g.drawLine(0, 0, width, 0);
//// g.drawLine(0, 1, 0, height);//左坚线
//// g.drawLine(width, 1, width, height);//右坚线
//// //水平第二条线(2)
//// g.setColor(topHightLight2);
//// g.drawLine(1, 1, width-NLMetalBorders.InternalFrameDialogBorder.insets.left, 1);
//// //水平第三条线(3)
//// g.setColor(topDarkHightLight2);
//// g.drawLine(2, 2, width-NLMetalBorders.InternalFrameDialogBorder.insets.left, 2);
////
//// NLTitlePane.paintTitlePane(g//左右空起的部分由Border绘制
//// , paintTitlePaneX//ZCMetalBorders.InternalFrameDialogBorder.insets.left
//// , paintTitlePaneY//ZCMetalBorders.InternalFrameDialogBorder.insets.left
//// , width-is.left*2 //注意此处也因BUG而作了填充区域的调整
//// , height, isSelected
//// , background, shadow);
//// //----------------------------- END
//// }
//// //正常无BUG时的填充
//// else
{
Insets frameInsets = frame.getInsets();
//** Swing BUG按理说此处是不需要传入frameInstes的因父类BasicInternalFrameTitlePane的布局
//是存在BUG布计算时没有把BorderInstes算入到xy的偏移中导致UI中paint时只能自行
//进行增益否则填充的图璩形肯定就因没有算上borderInstes而错位详见父类中的
//BasicInternalFrameTitlePane中内部类Handler的layoutContainer方法里
//getNorthPane().setBounds(..)这一段
// NLTitlePane.paintTitlePane(g
// , frameInsets.left//0
// , frameInsets.top//0
// , width-frameInsets.left-frameInsets.right//-0
// , height, isSelected
//// , background, shadow
// );
paintTitlePaneImpl(frameInsets, g, width, height, isSelected);
}
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 绘制标题栏背景END */
//----------------------------------------------------绘制标题及图标
int titleLength = 0;
int xOffset = leftToRight ? 5 : width - 5;
String frameTitle = frame.getTitle();
Icon icon = frame.getFrameIcon();
if (icon != null) {
if (!leftToRight)
xOffset -= icon.getIconWidth();
int iconY = ((height / 2) - (icon.getIconHeight() / 2));
icon.paintIcon(frame, g, xOffset + 2, iconY + 1);//默认是xOffset +0, iconY+0
xOffset += leftToRight ? icon.getIconWidth() + 5 : -5;
}
if (frameTitle != null) {
Font f = getFont();
g.setFont(f);
FontMetrics fm = MySwingUtilities2.getFontMetrics(frame, g, f);
int fHeight = fm.getHeight();
int yOffset = ((height - fm.getHeight()) / 2) + fm.getAscent();
Rectangle rect = new Rectangle(0, 0, 0, 0);
if (frame.isIconifiable())
rect = iconButton.getBounds();
else if (frame.isMaximizable())
rect = maxButton.getBounds();
else if (frame.isClosable())
rect = closeButton.getBounds();
int titleW;
if (leftToRight) {
if (rect.x == 0)
rect.x = frame.getWidth() - frame.getInsets().right - 2;
titleW = rect.x - xOffset - 4;
frameTitle = getTitle(frameTitle, fm, titleW);
} else {
titleW = xOffset - rect.x - rect.width - 4;
frameTitle = getTitle(frameTitle, fm, titleW);
xOffset -= MySwingUtilities2.stringWidth(frame, fm, frameTitle);
}
titleLength = MySwingUtilities2.stringWidth(frame, fm, frameTitle);
// g.setColor(Color.DARK_GRAY);//
// NLUtils.drawString(frame, g, frameTitle, xOffset+1, yOffset+1);
g.setColor(foreground);
// if(NLLookAndFeel.windowTitleAntialising)
// NLLookAndFeel.setAntiAliasing((Graphics2D) g,true);
MySwingUtilities2.drawString(frame, g, frameTitle, xOffset, yOffset);
// if(NLLookAndFeel.windowTitleAntialising)
// NLLookAndFeel.setAntiAliasing((Graphics2D) g,false);
xOffset += leftToRight ? titleLength + 5 : -5;
}
}
/**
* Paint title pane impl.
*
* @param frameInsets the frame insets
* @param g the g
* @param width the width
* @param height the height
* @param isSelected the is selected
*/
protected void paintTitlePaneImpl(Insets frameInsets, Graphics g,
int width, int height, boolean isSelected) {
BETitlePane.paintTitlePane(g,
frameInsets.left//0
,
frameInsets.top//0
,
width - frameInsets.left - frameInsets.right//-0
,
height, isSelected
// , background, shadow
);
}
// public void setPalette(boolean b)
// {
// isPalette = b;
//
// if (isPalette)
// {
// closeButton.setIcon(paletteCloseIcon);
// if (frame.isMaximizable())
// remove(maxButton);
// if (frame.isIconifiable())
// remove(iconButton);
// }
// else
// {
// closeButton.setIcon(closeIcon);
// if (frame.isMaximizable())
// add(maxButton);
// if (frame.isIconifiable())
// add(iconButton);
// }
// revalidate();
// repaint();
// }
/**
* Updates any state dependant upon the JInternalFrame being shown in a
* <code>JOptionPane</code>.
*/
private void updateOptionPaneState() {
int type = -2;
boolean closable = wasClosable;
Object obj = frame.getClientProperty("JInternalFrame.messageType");
if (obj == null)
// Don't change the closable state unless in an JOptionPane.
return;
if (obj instanceof Integer)
type = ((Integer) obj).intValue();
switch (type) {
case JOptionPane.ERROR_MESSAGE:
selectedBackgroundKey = "OptionPane.errorDialog.titlePane.background";
selectedForegroundKey = "OptionPane.errorDialog.titlePane.foreground";
selectedShadowKey = "OptionPane.errorDialog.titlePane.shadow";
closable = false;
break;
case JOptionPane.QUESTION_MESSAGE:
selectedBackgroundKey = "OptionPane.questionDialog.titlePane.background";
selectedForegroundKey = "OptionPane.questionDialog.titlePane.foreground";
selectedShadowKey = "OptionPane.questionDialog.titlePane.shadow";
closable = false;
break;
case JOptionPane.WARNING_MESSAGE:
selectedBackgroundKey = "OptionPane.warningDialog.titlePane.background";
selectedForegroundKey = "OptionPane.warningDialog.titlePane.foreground";
selectedShadowKey = "OptionPane.warningDialog.titlePane.shadow";
closable = false;
break;
case JOptionPane.INFORMATION_MESSAGE:
case JOptionPane.PLAIN_MESSAGE:
selectedBackgroundKey = selectedForegroundKey = selectedShadowKey = null;
closable = false;
break;
default:
selectedBackgroundKey = selectedForegroundKey = selectedShadowKey = null;
break;
}
if (closable != frame.isClosable())
frame.setClosable(closable);
}
/**
* {@inheritDoc}
*
* 改变父类的方法的可见性为public方便外界调用仅此而已.
*/
@Override
public void uninstallListeners() {
super.uninstallListeners();
}
}

View File

@ -0,0 +1,225 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEInternalFrameUI.java at 2015-2-1 20:25:37, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.internalframe;
import java.awt.Container;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.ActionMap;
import javax.swing.JComponent;
import javax.swing.JInternalFrame;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicInternalFrameUI;
/**
* 内部窗体UI实现类.
*
* BeautyEye外观实现中取消了isPalette的所有特殊处理isPalette及相关属性在
* 该外观中将失去意义请注意
*
* @author Jack Jiang
*/
public class BEInternalFrameUI extends BasicInternalFrameUI {
/**
* The title pane.
*/
private BEInternalFrameTitlePane titlePane;
/**
* The Constant metalPropertyChangeListener.
*/
private static final PropertyChangeListener metalPropertyChangeListener = new XZCMetalPropertyChangeHandler();
/**
* The Constant handyEmptyBorder.
*/
private static final Border handyEmptyBorder = new EmptyBorder(0, 0, 0, 0);
// protected static String IS_PALETTE = "JInternalFrame.isPalette";
/**
* The FRAM e_ type.
*/
private static String FRAME_TYPE = "JInternalFrame.frameType";
/**
* The NORMA l_ frame.
*/
private static String NORMAL_FRAME = "normal";
// private static String PALETTE_FRAME = "palette";
/**
* The OPTIO n_ dialog.
*/
private static String OPTION_DIALOG = "optionDialog";
/**
* Instantiates a new bE internal frame ui.
*
* @param b the b
*/
public BEInternalFrameUI(JInternalFrame b) {
super(b);
}
public static ComponentUI createUI(JComponent c) {
return new BEInternalFrameUI((JInternalFrame) c);
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
// Object paletteProp = c.getClientProperty(IS_PALETTE);
// if (paletteProp != null)
// {
// setPalette(((Boolean) paletteProp).booleanValue());
// }
Container content = frame.getContentPane();
stripContentBorder(content);
//c.setOpaque(false);
frame.setOpaque(false);
}
@Override
public void uninstallUI(JComponent c) {
frame = (JInternalFrame) c;
Container cont = ((JInternalFrame) (c)).getContentPane();
if (cont instanceof JComponent) {
JComponent content = (JComponent) cont;
if (content.getBorder() == handyEmptyBorder)
content.setBorder(null);
}
super.uninstallUI(c);
}
@Override
protected void installListeners() {
super.installListeners();
frame.addPropertyChangeListener(metalPropertyChangeListener);
}
@Override
protected void uninstallListeners() {
frame.removePropertyChangeListener(metalPropertyChangeListener);
super.uninstallListeners();
}
@Override
protected void installKeyboardActions() {
super.installKeyboardActions();
ActionMap map = SwingUtilities.getUIActionMap(frame);
if (map != null)
// BasicInternalFrameUI creates an action with the same name, we override
// it as Metal frames do not have system menus.
map.remove("showSystemMenu");
}
@Override
protected void uninstallKeyboardActions() {
super.uninstallKeyboardActions();
}
@Override
protected void uninstallComponents() {
titlePane = null;
super.uninstallComponents();
}
/**
* Strip content border.
*
* @param c the c
*/
private void stripContentBorder(Object c) {
if (c instanceof JComponent) {
JComponent contentComp = (JComponent) c;
Border contentBorder = contentComp.getBorder();
if (contentBorder == null || contentBorder instanceof UIResource)
contentComp.setBorder(handyEmptyBorder);
}
}
@Override
protected JComponent createNorthPane(JInternalFrame w) {
titlePane = new BEInternalFrameTitlePane(w);
return titlePane;
}
/**
* Sets the frame type.
*
* @param frameType the new frame type
*/
private void setFrameType(String frameType) {
if (frameType.equals(OPTION_DIALOG))
LookAndFeel.installBorder(frame, "InternalFrame.optionDialogBorder"); // titlePane.setPalette(false);
// else if (frameType.equals(PALETTE_FRAME))
// {
// LookAndFeel.installBorder(frame, "InternalFrame.paletteBorder");
//// titlePane.setPalette(true);
// }
else
LookAndFeel.installBorder(frame, "InternalFrame.border"); // titlePane.setPalette(false);
}
// // this should be deprecated - jcs
// public void setPalette(boolean isPalette)
// {
//// if (isPalette)
//// {
//// LookAndFeel.installBorder(frame, "InternalFrame.paletteBorder");
//// }
//// else
// {
// LookAndFeel.installBorder(frame, "InternalFrame.border");
// }
//// titlePane.setPalette(isPalette);
// }
private static class XZCMetalPropertyChangeHandler implements
PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent e) {
String name = e.getPropertyName();
JInternalFrame jif = (JInternalFrame) e.getSource();
if (!(jif.getUI() instanceof BEInternalFrameUI))
return;
BEInternalFrameUI ui = (BEInternalFrameUI) jif.getUI();
if (name.equals(FRAME_TYPE)) {
if (e.getNewValue() instanceof String)
ui.setFrameType((String) e.getNewValue());
} // else if (name.equals(IS_PALETTE))
// {
// if (e.getNewValue() != null)
// {
// ui.setPalette(((Boolean) e.getNewValue()).booleanValue());
// }
// else
// {
// ui.setPalette(false);
// }
// }
else if (name.equals(JInternalFrame.CONTENT_PANE_PROPERTY))
ui.stripContentBorder(e.getNewValue());
}
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:41, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.internalframe;
import javax.swing.UIManager;
import javax.swing.plaf.BorderUIResource;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.IconFactory;
import org.jackhuang.hmcl.laf.utils.UI;
import org.jackhuang.hmcl.laf.widget.border.BEShadowBorder;
public class __UI__ extends UI {
private static final IconFactory ICON = new IconFactory("internal_frame");
public static void uiImpl() {
//内部窗体的边框颜色BueaytyEye中无意义原因是BeautyEye LNF中的border是使用NP图实现
put("InternalFrame.borderColor", BeautyEyeLNFHelper.commonBackgroundColor);
put("InternalFrame.minimizeIconBackground", BeautyEyeLNFHelper.commonBackgroundColor);
// UIManager.put("InternalFrame.paletteCloseIcon", ICON.get("close")); //本属性在beautyEye中不会起效的
UIManager.put("InternalFrame.icon", ICON.get("icon"));
UIManager.put("InternalFrame.iconifyIcon", ICON.get("iconify"));
UIManager.put("InternalFrame.minimizeIcon", ICON.get("min"));
UIManager.put("InternalFrame.maximizeIcon", ICON.get("max"));
UIManager.put("InternalFrame.closeIcon", ICON.get("close"));
put("InternalFrameUI", BEInternalFrameUI.class);
// put("InternalFrame.paletteTitleHeight", 40); //本属性在beautyEye中不会起效的
// put("InternalFrame.titlePaneHeight", 38); //default is 25
// put("InternalFrame.borderWidth", 10);
Object internalFrameBorder = new BorderUIResource(new BEShadowBorder());
UIManager.put("InternalFrame.border", internalFrameBorder);
UIManager.put("InternalFrame.paletteBorder", internalFrameBorder);
UIManager.put("InternalFrame.optionDialogBorder", internalFrameBorder);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JDesktopPane相关ui属性设定
//JDesktopPane的背景色
put("Desktop.background", BeautyEyeLNFHelper.commonBackgroundColor);
//此属性暂无意义
// putInsetc("Desktop.minOnScreenInsets", 10, 10, 10, 10);//default is 3,3,3,3
//JDesktopPane中内部窗体最小化时的窗体组件宽度
put("DesktopIcon.width", 180); //默认是160
//BeautyEye LNF中内部窗体标题栏实现
put("DesktopIconUI", BEDesktopIconUI.class);
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEListUI.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.list;
import javax.swing.CellRendererPane;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicListUI;
/**
* JList的UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
* @version 1.0
*/
public class BEListUI extends BasicListUI {
public static ComponentUI createUI(JComponent c) {
return new BEListUI();
}
/**
* Initialize JList properties, e.g. font, foreground, and background, and
* add the CellRendererPane. The font, foreground, and background properties
* are only set if their current value is either null or a UIResource, other
* properties are set if the current value is null.
*
* @see #uninstallDefaults
* @see #installUI
* @see CellRendererPane
*/
@Override
protected void installDefaults() {
super.installDefaults();
//2012-08-30*******************************************************重要说明 START 对应BEComboBoxUI中的重要说明
//* 重要说明因BEListUI中为了使列表行单元高变的更高在MyDefaultListCellRenderer.java中
//* 像COmboxRender一样通过增到border不起效果它可能是BasicListUI的设计缺陷它要么取FixedCellHeight
//* 固定值要么取getPreferSize()即自动计算高度它似乎是不计入border的所以render设置border不起效
//* 所以只能为列表单元设置因定值list.setFixedCellHeight(30)但它将影响Combox里的行高也会变成30高
//* 所以BEComboBoxUI中要把本列表UI中强制设定的30高针对Combox还原成自动计算API中规定FixedCellHeight==-1即表示自动计算
//*************************************************************** 重要说明 END
//* 则jb2011加入表示列表单元固定高度默认值=-1即意味着行高自动计算
//* 使用BE LNF的项目如要恢复行高算动计算则显示设置列表的固定行高为-1即可
list.setFixedCellHeight(27);//32//30);// TODO 此设置值作一个UIManager属性就可以方便以后设置了-1是原系统默认值哦即自动计算单元高
//* 不需要了它样强制要求它为透明可能会影响以后用户的定制需求干脆
//* 设置它的背景为认白色也能达到想到的N9白色背景
// //此设置将取消列表背景的绘制以便BE LNF中绘制N9背景图哦
// list.setOpaque(false);
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* MyDefaultListCellRenderer.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.list;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JList;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
/**
* 列表单元的默认renderer实现类.
*
* @author Jack Jiang(jb2011@163.com), 2012-08-30
* @version 1.0
*/
public class MyDefaultListCellRenderer extends DefaultListCellRenderer {
private static final Icon9Factory ICON_9 = new Icon9Factory("list");
/**
* The is selected.
*/
protected boolean isSelected = false;
/**
* The is focuesed.
*/
protected boolean isFocuesed = false;
/**
* Instantiates a new my default list cell renderer.
*/
public MyDefaultListCellRenderer() {
//设置成透明背景则意味着不需要背景填充但本类中的应用场景有点特殊
//默认的render的UI里不需要绘制背景的情况下本类才可进行NinePatch图作为背景进行填充
setOpaque(false);
//** 要像Combox的render一样设置border没用因为列表单元不获得焦点时的border由UIManager属性List.cellNoFocusBorder决定
// //此内衬是决定列表单元间的上下左右空白的关键哦
// setBorder(BorderFactory.createEmptyBorder(5, 8, 5, 8));
}
@Override
public void paintComponent(Graphics g) {
if (isSelected)
//注意2012-09-03日用的该图片右边有一个像素的空白哦其实它是可以通过List.border的UI属性来调整的
//之所以没有用它调整就是为了日后可以使用N9图来自由调整而无需调整代码List.border的代码没置
ICON_9.get("selected_icon_bg")
.draw((Graphics2D) g, 0, 0, this.getWidth(), this.getHeight());
else {
// g.setColor(this.getBackground());
// //本Insets取this.getInsets()是符合Sun的设计初衷的但是不合理本身isPopupVisible==false
// //时的背景就是特殊情况不能与下拉项同等视之,所以此处用自定义的Insets来处理则在UI展现上更为合理
// //TODO 这个Instes可以作为UI属性ComboBox.popupNoVisibleBgInstes方便以后设置暂时先硬编码吧以后再说
// Insets is = new Insets(2,3,2,3);//this.getInsets();
//// g.fillRect(is.left, is.top
//// , this.getWidth()-is.left-is.right
//// , this.getHeight()-is.top-is.bottom);
// BEUtils.fillTextureRoundRec((Graphics2D)g, this.getBackground(), is.left, is.top
// , this.getWidth()-is.left-is.right
// , this.getHeight()-is.top-is.bottom,20,0);//20,20
}
// else
//注意本组件已经被设置成opaque=false即透明否则本方法还会填充默认背景那么选中时的
//N9图背景因先绘将会被覆盖哦所以要使用N9图作为选中时的背景则前提是本组件必须是透明
super.paintComponent(g);
}
@Override
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list,
value, index, isSelected, cellHasFocus);
this.isSelected = isSelected;
this.isFocuesed = cellHasFocus;
return c;
}
/**
* A subclass of DefaultListCellRenderer that implements UIResource.
* DefaultListCellRenderer doesn't implement UIResource directly so that
* applications can safely override the cellRenderer property with
* DefaultListCellRenderer subclasses.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with future Swing
* releases. The current serialization support is appropriate for short term
* storage or RMI between applications running the same version of Swing. As
* of 1.4, support for long term storage of all
* JavaBeans<sup><font size="-2">TM</font></sup>
* has been added to the <code>java.beans</code> package. Please see
* {@link java.beans.XMLEncoder}.
*/
public static class UIResource extends MyDefaultListCellRenderer
implements javax.swing.plaf.UIResource {
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.list;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Insets;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
public static void uiImpl() {
//通过此border可以调整整个列表的上下左右的空白
putBorder("List.border", 0, 0, 0, 0);
//本属性将决定已被选中的列表单元显示文本的上下左右空白哦
putBorder("List.focusCellHighlightBorder", 1, 8, 5, 3);
/* ~~注这个属性是jb2011为了更好的ui效果自已加的属性 */
putColor("List.focusSelectedCellHighlightBorderColor", 252, 87, 84); //Color.red
/* ~~注这个属性是jb2011为了更好的ui效果自已加的属性目的是使List.focusSelectedCellHighlightBorderColor有点立体效果哦 */
putColor("List.focusSelectedCellHighlightBorderHighlightColor", 255, 255, 255, 70);//注意这个颜色是半透明的哦
//列表单元获得焦点时的边框windows主题下是一个距形虚线框之前老也想不通的与左边隔一个像素的白边问题就是没设置它造成的
put("List.focusSelectedCellHighlightBorder", new FocusSelectedCellHighlightBorder());
//将决定正状态下的列表单元显示文本的上下左右空白哦
putBorder("List.cellNoFocusBorder", 1, 8, 5, 3);
put("List.background", Color.white);
put("List.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("List.selectionForeground", Color.white);//fgColor);
put("List.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
UIManager.put("List.cellRenderer", new MyDefaultListCellRenderer.UIResource());
put("ListUI", BEListUI.class);
}
/**
* 本border由Jack Jiang实现它是列表单元获得焦点时的边框windows外观
* 下是一个距形虚线框,本border当前的样式是在在最左边画的一条红色竖线
*/
static class FocusSelectedCellHighlightBorder extends AbstractBorder {
@Override
public Insets getBorderInsets(Component c) {
//Insets跟List.focusCellHighlightBorder 一样即可这样就能在视觉上保持一致罗不一样则会有移位的难看效果
return UIManager.getBorder("List.focusCellHighlightBorder").getBorderInsets(c);
}
@Override
public Insets getBorderInsets(Component c, Insets insets) {
return getBorderInsets(c);
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
//在左边划一条2像素宽的竖线
g.setColor(UIManager.getColor("List.focusSelectedCellHighlightBorderColor"));
g.fillRect(x, y + 0, 2, height - 1);//-2);//上下各空白一个像素目的是为了与render的N9图片背景配合形成更好的视觉效果
//再在上面的竖线右边划一条1像素宽的亮色竖线以便为上面的2像素竖线营造立体效果
/* ~~注这个属性是jb2011为了更好的ui效果自已加的属性目的是使List.focusSelectedCellHighlightBorder有点立体效果哦 */
g.setColor(UIManager.getColor("List.focusSelectedCellHighlightBorderHighlightColor"));
g.fillRect(x + 2, y + 0, 1, height - 1);//-2);
}
}
}

View File

@ -0,0 +1,112 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BECheckBoxMenuItemUI.java at 2015-2-1 20:25:39, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.menu;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.io.Serializable;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
import org.jackhuang.hmcl.laf.utils.IconFactory;
/**
* JCheckBoxMenuItem的UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
*/
public class BECheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI {
private static final IconFactory ICON = new IconFactory("menu_check");
/**
* 是否强制单项透明(当强制不透明时在普通状态下该item将不会被绘制背景.
*/
private static boolean enforceTransparent = true;
public static ComponentUI createUI(JComponent b) {
return new BECheckBoxMenuItemUI();
}
@Override
protected void paintBackground(Graphics g, JMenuItem menuItem,
Color bgColor) {
// if (WindowsMenuItemUI.isVistaPainting()) {
// WindowsMenuItemUI.paintBackground(accessor, g, menuItem, bgColor);
// return;
// }
// super.paintBackground(g, menuItem, bgColor);
// see parent!
ButtonModel model = menuItem.getModel();
Color oldColor = g.getColor();
int menuWidth = menuItem.getWidth();
int menuHeight = menuItem.getHeight();
Graphics2D g2 = (Graphics2D) g;
if (model.isArmed()
|| (menuItem instanceof JMenu && model.isSelected())) {
g.setColor(bgColor);
BEMenuUI.drawSelectedBackground(g, 0, 0, menuWidth, menuHeight);
// /****** 选中的背景样式现在是渐变加圆角填充了,impled by js */
// NLLookAndFeel.setAntiAliasing(g2, true);
// //矩形填充
// Paint oldpaint = g2.getPaint();
// GradientPaint gp = new GradientPaint(0, 0
// ,GraphicHandler.getColor(bgColor, 35, 35, 35)
// ,0, menuHeight,bgColor
// );
// g2.setPaint(gp);
// g.fillRoundRect(0, 0, menuWidth, menuHeight,5,5);
// g2.setPaint(oldpaint);
// NLLookAndFeel.setAntiAliasing(g2, false);
} else if (!enforceTransparent) {
g.setColor(menuItem.getBackground());
g.fillRect(0, 0, menuWidth, menuHeight);
}
g.setColor(oldColor);
}
/**
* @see
* com.sun.java.swing.plaf.windows.WindowsIconFactory.CheckBoxMenuItemIcon
*/
public static class CheckBoxMenuItemIcon implements Icon, UIResource, Serializable {
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
g.drawImage(ICON.get(((AbstractButton) c).getModel().isSelected() ? "checked" : "normal").getImage(),
x - 4, y - 3, null);
}
@Override
public int getIconWidth() {
return 16;
}// default 9
@Override
public int getIconHeight() {
return 16;
}// default 9
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEMenuBarUI.java at 2015-2-1 20:25:37, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.menu;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicMenuBarUI;
/**
* JMenuBar的UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
* @see com.sun.java.swing.plaf.windows.WindowsMenuBarUI
*/
public class BEMenuBarUI extends BasicMenuBarUI {
public static ComponentUI createUI(JComponent x) {
return new BEMenuBarUI();
}
@Override
public void paint(Graphics g, JComponent c) {
int width = c.getWidth();
int height = c.getHeight();
//背景划一个灰色底线方便与JMenuBar的顶层菜单项的底色融合
g.setColor(BEMenuUI.MENU_UNSELECTED_UNDERLINE_COLOR);
g.fillRect(0, height - BEMenuUI.DECORATED_UNDERLINE_HEIGHT, width, height);
}
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEMenuItemUI.java at 2015-2-1 20:25:38, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.menu;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.ButtonModel;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicMenuItemUI;
/**
* JMenuItem的UI实现类.
*
* 特别注意BasicMenuItemUI中针对Vista及后来的Windows版本预设了很多其它LNF不需要的属性
* 预设的属性详见BasicMenuItemUI及WindowsLookAndFeel中的initVistaComponentDefaults(..)方法.
* 这些属性只能会在vista及更新的windows平台上过运行时才会起效所以除此之外的windows测不出来,
* 容易出现ui视觉差异.
*
* @author Jack Jiang(jb2011@163.com)
*/
public class BEMenuItemUI extends BasicMenuItemUI {
/**
* 是否强制单项透明(当强制不透明时在普通状态下该item将不会被绘制背景.
*/
private static boolean enforceTransparent = true;// TODO 可以提炼成UI属性
public static ComponentUI createUI(JComponent c) {
return new BEMenuItemUI();
}
/**
* {@inheritDoc}
*
* @see com.sun.java.swing.plaf.windows.WindowsMenuItemUI#paintBackground(java.awt.Graphics, javax.swing.JMenuItem, java.awt.Color)
* @see javax.swing.plaf.basic.BasicMenuItemUI#paintBackground(java.awt.Graphics, javax.swing.JMenuItem, java.awt.Color)
*/
@Override
protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) {
ButtonModel model = menuItem.getModel();
Color oldColor = g.getColor();
int menuWidth = menuItem.getWidth();
int menuHeight = menuItem.getHeight();
Graphics2D g2 = (Graphics2D) g;
if (model.isArmed()
|| (menuItem instanceof JMenu && model.isSelected()))
//菜单项的样式绘制(用NinePatch图来填充)
BEMenuUI.drawSelectedBackground(g, 0, 0, menuWidth, menuHeight);
else if (!enforceTransparent) {
g.setColor(menuItem.getBackground());
g.fillRect(0, 0, menuWidth, menuHeight);
}
g.setColor(oldColor);
}
}

View File

@ -0,0 +1,306 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEMenuUI.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.menu;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.MenuElement;
import javax.swing.UIManager;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicMenuUI;
import org.jackhuang.hmcl.laf.BEUtils;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
import org.jackhuang.hmcl.laf.utils.WinUtils;
/**
* JMenuU的UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
* @see com.sun.java.swing.plaf.windows.WindowsMenuUI
*/
public class BEMenuUI extends BasicMenuUI {
//JMenuBar的顶层菜单项的装饰底线高度
public final static int DECORATED_UNDERLINE_HEIGHT = 2;// TODO 可以提炼成Ui属性哦
//顶层菜单项被选中的颜色
public final static Color MENU_SELECTED_UNDERLINE_COLOR = new Color(37, 147, 217);// TODO 可以提炼成Ui属性哦
//顶层菜单项未被选中的颜色
public final static Color MENU_UNSELECTED_UNDERLINE_COLOR = new Color(226, 230, 232);// TODO 可以提炼成Ui属性哦
protected Integer menuBarHeight;
protected boolean hotTrackingOn;
public static ComponentUI createUI(JComponent x) {
return new BEMenuUI();
}
/**
* {@inheritDoc}
*
* @see com.sun.java.swing.plaf.windows.WindowsMenuUI#installDefaults()
*/
@Override
protected void installDefaults() {
super.installDefaults();
// if (!WindowsLookAndFeel.isClassicWindows())
{
menuItem.setRolloverEnabled(true);
}
menuBarHeight = (Integer) UIManager.getInt("MenuBar.height");
Object obj = UIManager.get("MenuBar.rolloverEnabled");
hotTrackingOn = (obj instanceof Boolean) ? (Boolean) obj : true;
}
/**
* Draws the background of the menu.
*
* @param g the g
* @param menuItem the menu item
* @param bgColor the bg color
* @since 1.4
*
* @see com.sun.java.swing.plaf.windows.WindowsMenuUI#paintBackground(java.awt.Graphics, javax.swing.JMenuItem, java.awt.Color)
*/
@Override
protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) {
JMenu menu = (JMenu) menuItem;
ButtonModel model = menu.getModel();
Color oldColor = g.getColor();
int menuWidth = menu.getWidth();
int menuHeight = menu.getHeight();
// UIDefaults table = UIManager.getLookAndFeelDefaults();
// Color highlight = table.getColor("controlLtHighlight");
// Color shadow = table.getColor("controlShadow");
g.setColor(menu.getBackground());
g.fillRect(0, 0, menuWidth, menuHeight);
//给JMEnuBar的顶层菜单项中画一个灰色底线看起来美观
//位于菜单项里的MenuItem则不需要画这个底线要不然不好看哦
if (menu.isTopLevelMenu()) {
//未选中的装饰底线
//只要放在MenuBar最顶层的JMenu才需要画哦从而与底色融为一体
g.setColor(MENU_UNSELECTED_UNDERLINE_COLOR);
g.fillRect(0, menuHeight - DECORATED_UNDERLINE_HEIGHT, menuWidth, menuHeight);
}
//* >注意官方是判断menu.isOpaque()==false时才进入此if-else分支
//* >其实以下代码的意义是当是顶级Menu即直接放在MenuBar上的那层
//* >才需要调用以下分支而在win7下以下分支是不会被调用的WindowsLookAndfeel.initVistaComponentDefaults中
//* >处理了如果是vista则"MenuItem.opaque", "Menu.opaque", "CheckBoxMenuItem.opaque", "RadioButtonMenuItem.opaque"
//* >默认都设置成了false即默认透明官方逻辑可能是透明体就意味着是顶级menu了
//* >那么win7下将会出现错误的表现无法区分是不是顶级menu也就无法区别paint出不同的样子了.
//* >那么官方为何没收到bug报告呢我分析可能还没有人面对到BeautyEye这样需要对Menu进行较复杂样式需求的场景
//* >即把顶级menu和内层menu分的很清
//* >目前BeautyEye的实现即menu.isTopLevelMenu()==true时即进入本分支
//* >才是比较合理的当然有待实践检验或许官方有其它考虑 -- commet by Jack Jiang 2012-09-14
if (menu.isTopLevelMenu())//menu.isOpaque())
{
//JMebuBar的顶层菜单项被选中或鼠标停留时
if (model.isArmed() || model.isSelected()) {
Color c = MENU_SELECTED_UNDERLINE_COLOR;
g.setColor(c);
//先填充一个装饰3角形用于在UI上提示用户它被选中了
// x2,y2
//
//x1,y1 x3,y3
int tW = 7, tH = 3;
int x1 = menuWidth / 2 - tW / 2;
int y1 = menuHeight - DECORATED_UNDERLINE_HEIGHT;
int x2 = menuWidth / 2;
int y2 = menuHeight - DECORATED_UNDERLINE_HEIGHT - tH;
int x3 = menuWidth / 2 + tW / 2;
int y3 = menuHeight - DECORATED_UNDERLINE_HEIGHT;
//反走样
BEUtils.setAntiAliasing((Graphics2D) g, true);
BEUtils.fillTriangle(g, x1, y1, x2, y2, x3, y3, c);
BEUtils.setAntiAliasing((Graphics2D) g, false);
//再填充一个底线用于装饰
g.fillRect(0, menuHeight - DECORATED_UNDERLINE_HEIGHT, menuWidth, DECORATED_UNDERLINE_HEIGHT);//menuHeight);
} else if (model.isRollover() && model.isEnabled()) {
// Only paint rollover if no other menu on menubar is selected
boolean otherMenuSelected = false;
MenuElement[] menus = ((JMenuBar) menu.getParent())
.getSubElements();
for (MenuElement menu1 : menus)
if (((JMenuItem) menu1).isSelected()) {
otherMenuSelected = true;
break;
}
if (!otherMenuSelected) {
g.setColor(MENU_SELECTED_UNDERLINE_COLOR);//selectionBackground);// Uses protected
// g.fillRect(0, 0, menuWidth, menuHeight);
//再填充一个底线用于装饰
g.fillRect(0, menuHeight - DECORATED_UNDERLINE_HEIGHT, menuWidth, DECORATED_UNDERLINE_HEIGHT);//menuHeight);
}
}
} // add by Jack JiangJMebuBar的内层父级菜单项的样式绘制
else if (model.isArmed() || (menuItem instanceof JMenu
&& model.isSelected())) {
//用NinePatch图来填充
drawSelectedBackground(g, 0, 0, menuWidth, menuHeight);
}
g.setColor(oldColor);
}
public static void drawSelectedBackground(Graphics g, int x, int y, int w, int h) {
g.setColor(UIManager.getColor("MenuItem.selectionBackground"));
g.fillRect(0, 0, w, h);
}
/**
* Method which renders the text of the current menu item.
* <p>
* @param g Graphics context
* @param menuItem Current menu item to render
* @param textRect Bounding rectangle to render the text.
* @param text String to render
* @since 1.4
*
* @see com.sun.java.swing.plaf.windows.WindowsMenuUI#paintText(java.awt.Graphics, javax.swing.JMenuItem, java.awt.Rectangle, java.lang.String)
*/
@Override
protected void paintText(Graphics g, JMenuItem menuItem,
Rectangle textRect, String text) {
//================= commet by Jack Jiang START
// if (WindowsMenuItemUI.isVistaPainting()) {
// WindowsMenuItemUI.paintText(accessor, g, menuItem, textRect, text);
// return;
// }
//================= commet by Jack Jiang END
JMenu menu = (JMenu) menuItem;
ButtonModel model = menuItem.getModel();
Color oldColor = g.getColor();
// Only paint rollover if no other menu on menubar is selected
boolean paintRollover = model.isRollover();
if (paintRollover && menu.isTopLevelMenu()) {
MenuElement[] menus = ((JMenuBar) menu.getParent()).getSubElements();
for (MenuElement menu1 : menus)
if (((JMenuItem) menu1).isSelected()) {
paintRollover = false;
break;
}
}
if ((model.isSelected()
&& ( // WindowsLookAndFeel.isClassicWindows() ||
!menu.isTopLevelMenu()))
|| ( // BEXPStyle.getXP() != null &&
(paintRollover || model.isArmed() || model.isSelected())))
g.setColor(selectionForeground); // Uses protected field.
//================= add by Jack Jiang START
//特殊处理顶级菜单项就是直接放在JMenuBar上的那一层使之在被选中或rover等状态时保持黑色或其它颜色
//目的是为了配合整个菜单项的L&F效果并没有过多的用途此颜色可提取作为UIManager的自定义属性哦
if (menu.isTopLevelMenu())
g.setColor(new Color(35, 35, 35));//用MaxOS X的经典黑
//================= add by Jack Jiang END
// WindowsGraphicsUtils.paintText(g, menuItem, textRect, text, 0);
WinUtils.paintText(g, menuItem, textRect, text, 0);
g.setColor(oldColor);
}
/**
* {@inheritDoc}
*
* @see
* com.sun.java.swing.plaf.windows.WindowsMenuUI#createMouseInputListener(javax.swing.JComponent)
*/
@Override
protected MouseInputListener createMouseInputListener(JComponent c) {
return new BEMouseInputHandler();
}
/**
* This class implements a mouse handler that sets the rollover flag to true
* when the mouse enters the menu and false when it exits.
*
* @since 1.4
* @see com.sun.java.swing.plaf.windows.WindowsMenuUI.MouseInputHandler
*/
protected class BEMouseInputHandler extends BasicMenuUI.MouseInputHandler {
@Override
public void mouseEntered(MouseEvent evt) {
super.mouseEntered(evt);
JMenu menu = (JMenu) evt.getSource();
if (hotTrackingOn && menu.isTopLevelMenu() && menu.isRolloverEnabled()) {
menu.getModel().setRollover(true);
menuItem.repaint();
}
}
@Override
public void mouseExited(MouseEvent evt) {
super.mouseExited(evt);
JMenu menu = (JMenu) evt.getSource();
ButtonModel model = menu.getModel();
if (menu.isRolloverEnabled()) {
model.setRollover(false);
menuItem.repaint();
}
}
}
/**
* {@inheritDoc}
*
* @see
* com.sun.java.swing.plaf.windows.WindowsMenuUI#getPreferredMenuItemSize(javax.swing.JComponent,
* javax.swing.Icon, javax.swing.Icon, int)
*/
@Override
protected Dimension getPreferredMenuItemSize(JComponent c,
Icon checkIcon,
Icon arrowIcon,
int defaultTextIconGap) {
Dimension d = super.getPreferredMenuItemSize(c, checkIcon, arrowIcon,
defaultTextIconGap);
// Note: When toolbar containers (rebars) are implemented, only do
// this if the JMenuBar is not in a rebar (i.e. ignore the desktop
// property win.menu.height if in a rebar.)
if (c instanceof JMenu && ((JMenu) c).isTopLevelMenu()
&& menuBarHeight != null && d.height < menuBarHeight)
d.height = menuBarHeight;
return d;
}
}

View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEPopupMenuSeparatorUI.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.menu;
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import javax.swing.JComponent;
import javax.swing.JSeparator;
import javax.swing.LookAndFeel;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.SeparatorUI;
/**
* JPopupMenuSeparator的UI实现.
*
* @author Jack Jiang(jb2011@163.com)
* @version 1.0
*/
public class BEPopupMenuSeparatorUI extends SeparatorUI {
public static ComponentUI createUI(JComponent c) {
return new BEPopupMenuSeparatorUI();
}
@Override
public void installUI(JComponent c) {
installDefaults((JSeparator) c);
installListeners((JSeparator) c);
}
@Override
public void uninstallUI(JComponent c) {
uninstallDefaults((JSeparator) c);
uninstallListeners((JSeparator) c);
}
protected void installDefaults(JSeparator s) {
LookAndFeel.installColors(s, "Separator.background", "Separator.foreground");
LookAndFeel.installProperty(s, "opaque", Boolean.FALSE);
}
protected void uninstallDefaults(JSeparator s) {
}
protected void installListeners(JSeparator s) {
}
protected void uninstallListeners(JSeparator s) {
}
@Override
public void paint(Graphics g, JComponent c) {
int w = c.getWidth(), h = c.getHeight();
Graphics2D g2 = (Graphics2D) g;
if (((JSeparator) c).getOrientation() == JSeparator.VERTICAL) {
//垂直坚线原始代码
//TODO 垂直样式的竖线有时间再实现吧垂直竖线默认用于JToolBar里
g.setColor(c.getForeground());
g.drawLine(0, 0, 0, c.getHeight());
g.setColor(c.getBackground());
g.drawLine(1, 0, 1, c.getHeight());
} else // HORIZONTAL
drawHorizonal(g2, c, w, h);
}
/**
* 以水平方向绘制分隔线样式.
*/
private void drawHorizonal(Graphics2D g2, JComponent c, int w, int h) {
//** 绘制border的底线
//虚线样式
Stroke oldStroke = g2.getStroke();
Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0);//实线空白
g2.setStroke(sroke);
//底边上浅灰色
// g2.setColor(new Color(180,180,180));
g2.setColor(c.getForeground());
g2.drawLine(0, h - 2, w - 1, h - 2); // draw bottom1
//底边下白色绘制一条白色虚线的目的是与上面的灰线产生较强对比度从而形成立体效果
//本L&F实现中因与Panel的底色对比度不够强烈而立体感不明显颜色越深的底色最终效果越明显
// g2.setColor(Color.white);
g2.setColor(c.getBackground());
g2.drawLine(0, h - 1, w - 1, h - 1);//draw bottom2
g2.setStroke(oldStroke);
}
@Override
public Dimension getPreferredSize(JComponent c) {
if (((JSeparator) c).getOrientation() == JSeparator.VERTICAL)
return new Dimension(2, 0);
else
return new Dimension(0, 3);
}
@Override
public Dimension getMinimumSize(JComponent c) {
return null;
}
@Override
public Dimension getMaximumSize(JComponent c) {
return null;
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEPopupMenuUI.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.menu;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicPopupMenuUI;
/**
* BeautyEye L&F的弹出菜单主类实现类.
*
* 兼容性说明WindowsPopupMenuUI类在java1.6.0_u10可能不仅限于1.6.0_u10但java1.6.0中不存在这个问题
* 中会判断如果是在Vista或者说xp平台时(测试证明是在win7平台会有这些问题)会用windows系
* 统实现进行背景填充而在1.6.0_u18可能不限于此版本中取消了这样的判断改为直接继续
* BasicPopupMenuUI的实默认实现因此而带来的差异使得BE LNF在不同的java版本里u10
* 错误地使用windows系统实现.本类的目的就是要去掉这种差异仍然交由父类BasicPopupMenuUI 实现即可类似的官方Metal
* LNF也是采用了BeautyEye一样的处理逻辑.
*
* @author Jack Jiang(jb2011@163.com), 2012-09-14
* @version 1.0
* @since 3.1
*
* @see com.sun.java.swing.plaf.windows.WindowsPopupMenuUI
*/
public class BEPopupMenuUI extends BasicPopupMenuUI {
public static ComponentUI createUI(JComponent c) {
return new BEPopupMenuUI();
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BERadioButtonMenuItemUI.java at 2015-2-1 20:25:37, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.menu;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.io.Serializable;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicRadioButtonMenuItemUI;
import org.jackhuang.hmcl.laf.utils.IconFactory;
/**
* JRadioButtonMenuItem的UI实现.
*
* @author Jack Jiang(jb2011@163.com)
* @version 1.0
*/
public class BERadioButtonMenuItemUI extends BasicRadioButtonMenuItemUI {
private static final IconFactory ICON = new IconFactory("menu_radio");
public static ComponentUI createUI(JComponent b) {
return new BERadioButtonMenuItemUI();
}
/**
* Draws the background of the menu item.
*
* @param g the paint graphics
* @param menuItem menu item to be painted
* @param bgColor selection background color
* @since 1.4
* @see
* javax.swing.plaf.basic.BasicMenuItemUI#paintBackground(java.awt.Graphics,
* javax.swing.JMenuItem, java.awt.Color)
*/
@Override
protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) {
ButtonModel model = menuItem.getModel();
Color oldColor = g.getColor();
int menuWidth = menuItem.getWidth();
int menuHeight = menuItem.getHeight();
if (menuItem.isOpaque()) {
if (model.isArmed() || (menuItem instanceof JMenu && model.isSelected())) {
g.setColor(bgColor);
g.fillRect(0, 0, menuWidth, menuHeight);
} else {
g.setColor(menuItem.getBackground());
g.fillRect(0, 0, menuWidth, menuHeight);
}
g.setColor(oldColor);
} else if (model.isArmed() || (menuItem instanceof JMenu
&& model.isSelected()))
// g.setColor(bgColor);
// g.fillRect(0,0, menuWidth, menuHeight);
// g.setColor(oldColor);
//由jb2011改用NinePatch图来填充
BEMenuUI.drawSelectedBackground(g, 0, 0, menuWidth, menuHeight);
}
/**
* @see com.sun.java.swing.plaf.windows.WindowsIconFactory.RadioButtonMenuItemIcon
*/
public static class RadioButtonMenuItemIcon implements Icon, UIResource, Serializable {
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
//* 注意当用于windows平台专用主类且处于Vista及更高版win时要做不一样的处理哦
g.drawImage(ICON.get(((AbstractButton) c).getModel().isSelected() ? "checked" : "normal").getImage(),
x - 4, y - 4, null);
}
@Override
public int getIconWidth() {
return 16;
}//default 6
@Override
public int getIconHeight() {
return 16;
}//default 6
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.menu;
import java.awt.Color;
import javax.swing.UIManager;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
public static void uiImpl() {
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> margin和border设置 START
// UIManager.put("MenuBar.border",new org.jb2011.lnf.windows2.ch10.EWindowsMenuBarUI.MenuBarBorder(Color.red,Color.BLUE));
//去掉菜单条下方的border默认是一个2个像素高的横线参见WindowsMenuBarUI.MenuBarBorder
putBorder("MenuBar.border");
//提示margin与border并存设置情况容易产生混知其实官方实现是当设置margin时则Border就使用
//marginBorder该Border就是用的这个margin来作它的Insets的
//BueatyEye LNF中推荐实践是抛弃margin的概念省的混淆直接使用border在其上直接给于insets即可
putInsets("CheckBoxMenuItem.margin", 0, 0, 0, 0);
putInsets("RadioButtonMenuItem.margin", 0, 0, 0, 0);//iuir);
putInsets("Menu.margin", 0, 0, 0, 0);//windows lnf中默认是2222
putInsets("MenuItem.margin", 0, 0, 0, 0);//windows lnf中默认是2222
// putInsets("MenuItem.margin", 10, 2, 10, 2);//top=2,left=2,bottom=2,right=2
//请注意上面的margin已经全设为0了哦
putBorder("Menu.border", 4, 3, 5, 3);//javax.swing.plaf.basic.BasicBorders.MarginBorder;
putBorder("MenuItem.border", 4, 3, 5, 3);//
putBorder("CheckBoxMenuItem.border", 4, 3, 5, 3);//javax.swing.plaf.basic.BasicBorders.MarginBorder;
putBorder("RadioButtonMenuItem.border", 4, 3, 5, 3);//
// putBorder("PopupMenu.border", 20, 10, 20, 10); //
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> margin和border设置 END
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 颜色设置 START
put("MenuBar.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("RadioButtonMenuItem.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("Menu.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("PopupMenu.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("CheckBoxMenuItem.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("MenuItem.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("MenuBar.background", BeautyEyeLNFHelper.commonBackgroundColor);
put("Menu.background", new Color(255, 255, 255, 0));
put("PopupMenu.background", new Color(255, 255, 255, 0));
put("RadioButtonMenuItem.disabledForeground", BeautyEyeLNFHelper.commonDisabledForegroundColor);
put("MenuItem.disabledForeground", BeautyEyeLNFHelper.commonDisabledForegroundColor);
put("Menu.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor);
put("MenuItem.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor);
put("CheckBoxMenuItem.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor);
put("RadioButtonMenuItem.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor);
put("Menu.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
put("MenuItem.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
put("CheckBoxMenuItem.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
put("RadioButtonMenuItem.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 颜色设置 END
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 杂项设置 START
//本值意味着弹出菜单X轴方向上的偏移量因BE LNF中加了边框所以要负偏移以便得弹出菜单主体能与菜单项对齐好看一些
put("Menu.menuPopupOffsetX", -3);//win lnf中默认值是0
//本值意味着弹出菜单Y轴方向上的偏移量因BE LNF中加了边框所以要负偏移以便得弹出菜单主体能与菜单项对齐好看一些
put("Menu.menuPopupOffsetY", 2);///win lnf默认值是0
//本值意味着弹出子菜单X轴方向上的偏移量因BE LNF中加了边框所以要负偏移以便得弹出菜单主体能与菜单项对齐好看一些
put("Menu.submenuPopupOffsetX", -2);///win lnf默认值是-4
//本值意味着弹出子菜单Y轴方向上的偏移量因BE LNF中加了边框所以要负偏移以便得弹出菜单主体能与菜单项对齐好看一些
put("Menu.submenuPopupOffsetY", -5);///win lnf默认值是-3
//多选按钮式的菜单项选中与否的图标实现设定
UIManager.put("CheckBoxMenuItem.checkIcon", new BECheckBoxMenuItemUI.CheckBoxMenuItemIcon());
//单选按钮式的菜单项选中与否的图标实现设定
UIManager.put("RadioButtonMenuItem.checkIcon", new BERadioButtonMenuItemUI.RadioButtonMenuItemIcon());
//加高菜单条提升视觉体验
put("MenuBar.height", 30);//default value is 19
//此属性true时表明禁用的菜单项将不能被rover否则有rover效果BE LNF中
//因禁用状态rover时的字体色影响视觉效果所以干脆禁用之逻辑上也很合理
put("MenuItem.disabledAreNavigable", false);// windows lnf中默认是true
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 杂项设置 END
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UI实现类设置 START
put("MenuBarUI", BEMenuBarUI.class);
put("MenuUI", BEMenuUI.class);
put("MenuItemUI", BEMenuItemUI.class);
put("RadioButtonMenuItemUI", BERadioButtonMenuItemUI.class);
put("CheckBoxMenuItemUI", BECheckBoxMenuItemUI.class);
put("PopupMenuSeparatorUI", BEPopupMenuSeparatorUI.class);
put("PopupMenuUI", BEPopupMenuUI.class);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UI实现类设置 END
}
}

View File

@ -1,252 +0,0 @@
/*
* $Id: MetroGraphicsUtils.java,v 1.9 2005/12/05 15:00:55 kizune Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jackhuang.hmcl.laf.painter;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import javax.swing.Timer;
import javax.swing.plaf.synth.SynthConstants;
import javax.swing.plaf.synth.SynthContext;
import javax.swing.plaf.synth.SynthPainter;
import org.jackhuang.hmcl.util.ui.GraphicsUtils;
import org.jackhuang.hmcl.laf.ConstomButton;
/**
* ButtonPainter - handles painting Nimbus style buttons with Java2D
*
* @author Created by Jasper Potts (Jan 4, 2007)
* @version 1.0
*/
public class ButtonPainter extends SynthPainter {
private static final String DEFAULT_NORMAL = "D5D5D5";
private static final Color[] DEFAULT_NORMAL_FG = new Color[]{
GraphicsUtils.getWebColor(DEFAULT_NORMAL),
GraphicsUtils.getWebColor(DEFAULT_NORMAL)
};
private static final String DEFAULT_PRELIGHT = "A9A9A9";
private static final Color[] DEFAULT_PRELIGHT_FG = new Color[]{
GraphicsUtils.getWebColor(DEFAULT_PRELIGHT),
GraphicsUtils.getWebColor(DEFAULT_PRELIGHT)
};
private static final String DEFAULT_ACTIVE = "222222";
private static final Color[] DEFAULT_ACTIVE_FG = new Color[]{
GraphicsUtils.getWebColor(DEFAULT_ACTIVE),
GraphicsUtils.getWebColor(DEFAULT_ACTIVE)
};
private static final Color[] DISABLED_BG = new Color[]{
GraphicsUtils.getWebColor("E3EFE9"),
GraphicsUtils.getMidWebColor("E3EFE9", "DFE2E6"),
GraphicsUtils.getWebColor("DFE2E6"),
GraphicsUtils.getMidWebColor("DFE2E6", "D6D9DF"),
GraphicsUtils.getWebColor("D6D9DF"),
GraphicsUtils.getWebColor("D6D9DF"),
GraphicsUtils.getMidWebColor("D6D9DF", "D8DBE1"),
GraphicsUtils.getWebColor("D8DBE1"),
GraphicsUtils.getWebColor("DADDE3")
};
private static final Color[] DISABLED_FG = new Color[]{
GraphicsUtils.getWebColor("C9CCD2"),
GraphicsUtils.getWebColor("C9CCD2"),
GraphicsUtils.getWebColor("BCBFC5"),
GraphicsUtils.getWebColor("BCBFC5")
};
private static boolean processCustomButton(final ConstomButton c, int add) {
if (c.drawPercent == 0 || c.drawPercent == 100) {
Timer t = new Timer(1, null);
t.addActionListener(x -> {
c.drawPercent += add;
if (c.drawPercent > 100 && add > 0) {
c.drawPercent = 100;
t.stop();
} else if (c.drawPercent < 0 && add < 0) {
c.drawPercent = 0;
t.stop();
} else
c.updateUI();
});
t.start();
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public void paintButtonBackground(SynthContext context, Graphics g, int x, int y, int w, int h) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color[] fg, bg;
if ((context.getComponentState() & SynthConstants.DEFAULT) != 0)
if ((context.getComponentState() & SynthConstants.PRESSED) != 0)
if (context.getComponent() instanceof ConstomButton) {
ConstomButton c = (ConstomButton) context.getComponent();
fg = new Color[]{c.activeFg, c.activeFg};
bg = new Color[]{c.activeFg, c.activeFg};
} else {
fg = DEFAULT_ACTIVE_FG;
bg = DEFAULT_ACTIVE_FG;
}
else if ((context.getComponentState() & SynthConstants.DISABLED) != 0)
return; //fg = DISABLED_FG;
//bg = DISABLED_BG;
else if ((context.getComponentState() & SynthConstants.MOUSE_OVER) != 0)
if (context.getComponent() instanceof ConstomButton) {
final ConstomButton c = (ConstomButton) context.getComponent();
if (!processCustomButton(c, 1))
return;
Color fgs = GraphicsUtils.getMidWebColor(c.normalFg, c.prelightFg, c.drawPercent);
Color bgs = GraphicsUtils.getMidWebColor(c.normalBg, c.prelightBg, c.drawPercent);
fg = new Color[]{fgs, fgs};
bg = new Color[]{bgs, bgs};
} else {
fg = DEFAULT_PRELIGHT_FG;
bg = DEFAULT_PRELIGHT_FG;
}
else if (context.getComponent() instanceof ConstomButton) {
final ConstomButton c = (ConstomButton) context.getComponent();
if (!processCustomButton(c, -1))
return;
Color fgs = GraphicsUtils.getMidWebColor(c.normalFg, c.prelightFg, c.drawPercent);
Color bgs = GraphicsUtils.getMidWebColor(c.normalBg, c.prelightBg, c.drawPercent);
fg = new Color[]{fgs, fgs};
bg = new Color[]{bgs, bgs};
} else {
fg = DEFAULT_NORMAL_FG;
bg = DEFAULT_NORMAL_FG;
}
else if ((context.getComponentState() & SynthConstants.PRESSED) != 0)
if (context.getComponent() instanceof ConstomButton) {
ConstomButton c = (ConstomButton) context.getComponent();
fg = new Color[]{c.activeFg, c.activeFg};
bg = new Color[]{c.activeFg, c.activeFg};
} else {
fg = DEFAULT_ACTIVE_FG;
bg = DEFAULT_ACTIVE_FG;
}
else if ((context.getComponentState() & SynthConstants.DISABLED) != 0)
return; //fg = DISABLED_FG;
//bg = DISABLED_BG;
else if ((context.getComponentState() & SynthConstants.MOUSE_OVER) != 0)
if (context.getComponent() instanceof ConstomButton) {
final ConstomButton c = (ConstomButton) context.getComponent();
if (!processCustomButton(c, 1))
return;
Color fgs = GraphicsUtils.getMidWebColor(c.normalFg, c.prelightFg, c.drawPercent);
Color bgs = GraphicsUtils.getMidWebColor(c.normalBg, c.prelightBg, c.drawPercent);
fg = new Color[]{fgs, fgs};
bg = new Color[]{bgs, bgs};
} else if (context.getComponent() instanceof ConstomButton) {
ConstomButton c = (ConstomButton) context.getComponent();
fg = new Color[]{c.prelightFg, c.prelightFg};
bg = new Color[]{c.prelightBg, c.prelightBg};
} else {
fg = DEFAULT_PRELIGHT_FG;
bg = DEFAULT_PRELIGHT_FG;
}
else if (context.getComponent() instanceof ConstomButton) {
final ConstomButton c = (ConstomButton) context.getComponent();
if (!processCustomButton(c, -1))
return;
Color fgs = GraphicsUtils.getMidWebColor(c.normalFg, c.prelightFg, c.drawPercent);
Color bgs = GraphicsUtils.getMidWebColor(c.normalBg, c.prelightBg, c.drawPercent);
fg = new Color[]{fgs, fgs};
bg = new Color[]{bgs, bgs};
} else {
fg = DEFAULT_NORMAL_FG;
bg = DEFAULT_NORMAL_FG;
}
/*w = w - 2;
h = h - 2;
g2.setPaint(new LinearGradientPaint(x, y, x, y + h,
new float[]{0, 1}, bg));
g2.fillRect(x, y, w, h);
g2.setPaint(new LinearGradientPaint(x, y, x, y + h,
new float[]{0, 1}, fg));
g2.drawRect(x, y, w, h);*/
int radix = (context.getComponent() instanceof ConstomButton) ? ((ConstomButton) context.getComponent()).radix : 0;
g2.setColor(fg[0]);
RoundRectangle2D fgshape = new RoundRectangle2D.Float(x, y, w, h, radix, radix);
g2.draw(fgshape);
g2.setColor(bg[0]);
RoundRectangle2D bgshape = new RoundRectangle2D.Float(x, y, w, h, radix, radix);
g2.fill(bgshape);
}
@Override
public void paintToggleButtonBackground(SynthContext context, Graphics g, int x, int y, int w, int h) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color[] fg, bg;
//if ((context.getComponentState() & SynthConstants.DEFAULT) != 0)
if ((context.getComponentState() & SynthConstants.PRESSED) != 0 || (context.getComponentState() & SynthConstants.SELECTED) != 0) {
fg = DEFAULT_ACTIVE_FG;
bg = DEFAULT_ACTIVE_FG;
} else if ((context.getComponentState() & SynthConstants.DISABLED) != 0) {
fg = DISABLED_FG;
bg = DISABLED_BG;
} else if ((context.getComponentState() & SynthConstants.MOUSE_OVER) != 0) {
fg = DEFAULT_PRELIGHT_FG;
bg = DEFAULT_PRELIGHT_FG;
} else {
fg = DEFAULT_NORMAL_FG;
bg = DEFAULT_NORMAL_FG;
}
/*else if ((context.getComponentState() & SynthConstants.PRESSED) != 0 || (context.getComponentState() & SynthConstants.SELECTED) != 0) {
fg = DEFAULT_ACTIVE_FG;
bg = DEFAULT_ACTIVE_FG;
} else if ((context.getComponentState() & SynthConstants.DISABLED) != 0) {
fg = DISABLED_FG;
bg = DISABLED_BG;
} else if ((context.getComponentState() & SynthConstants.MOUSE_OVER) != 0) {
fg = DEFAULT_PRELIGHT_FG;
bg = DEFAULT_PRELIGHT_FG;
} else {
fg = DEFAULT_NORMAL_FG;
bg = DEFAULT_NORMAL_FG;
}*/
g2.setColor(fg[0]);
Rectangle2D fgshape = new Rectangle2D.Float(x, y, w, h);
g2.draw(fgshape);
g2.setColor(bg[0]);
Rectangle2D bgshape = new Rectangle2D.Float(x, y, w, h);
g2.fill(bgshape);
/*g2.setPaint(new LinearGradientPaint(x, y, x, y + h,
new float[]{0, 1}, bg));
g2.fillRect(x, y, w, h);
g2.setPaint(new LinearGradientPaint(x, y, x, y + h,
new float[]{0, 1}, fg));
g2.drawRect(x, y, w, h);*/
}
}

View File

@ -1,81 +0,0 @@
/*
* $Id: MetroGraphicsUtils.java,v 1.9 2005/12/05 15:00:55 kizune Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jackhuang.hmcl.laf.painter;
import org.jackhuang.hmcl.util.ui.GraphicsUtils;
import javax.swing.plaf.synth.SynthContext;
import javax.swing.plaf.synth.SynthPainter;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
/**
* ProgressPainter - Synth painter for Nimbus progressbars
*
* @author Created by Jasper Potts (Jan 3, 2007)
* @version 1.0
*/
public class ProgressPainter extends SynthPainter {
private static final float[] NORMAL_BG_PTS = new float[]{0, 1};
private static final Color[] NORMAL_BG = new Color[]{
GraphicsUtils.getWebColor("c6c6c6"),
GraphicsUtils.getWebColor("c6c6c6")
};
private static final float[] BAR_FG_PTS = new float[]{0, 1};
private static final Color[] BAR_FG = new Color[]{
GraphicsUtils.getWebColor("41B1E1"),
GraphicsUtils.getWebColor("41B1E1")
};
/**
* {@inheritDoc}
*/
@Override
public void paintProgressBarBackground(SynthContext context, Graphics g, int x, int y, int w, int h,
int orientation) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setPaint(new LinearGradientPaint(x, y + 2, x, y + h - 4, NORMAL_BG_PTS, NORMAL_BG));
if (x + 2 < w - 5 && y + 2 < h - 5)
g2.fillRect(x + 2, y + 2, w - 5, h - 5);
}
/**
* {@inheritDoc}
*/
@Override
public void paintProgressBarForeground(SynthContext context, Graphics g, int x, int y, int w, int h,
int orientation) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setPaint(new LinearGradientPaint(x, y + 2, x, y + h - 2, BAR_FG_PTS, BAR_FG));
if (x + 2 < w - 5 && y + 2 < h - 5)
g2.fillRect(x + 2, y + 2, w - 5, h - 5);
}
/**
* {@inheritDoc}
*/
@Override
public void paintProgressBarBorder(SynthContext context, Graphics g, int x, int y, int w, int h, int orientation) {
}
}

View File

@ -1,99 +0,0 @@
/*
* $Id: NimbusGraphicsUtils.java,v 1.9 2005/12/05 15:00:55 kizune Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jackhuang.hmcl.laf.painter;
import javax.swing.plaf.synth.SynthContext;
import javax.swing.plaf.synth.SynthPainter;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.plaf.synth.SynthConstants;
import org.jackhuang.hmcl.util.ui.GraphicsUtils;
/**
* TextFieldPainter
*
* @author Created by Jasper Potts (Jan 4, 2007)
* @version 1.0
*/
public class TextFieldPainter extends SynthPainter {
private boolean fill = true;
private static final Color DISABLED = GraphicsUtils.getWebColor("F3F3F3"),
NORMAL = GraphicsUtils.getWebColor("CCCCCC"),
FOCUSED = GraphicsUtils.getWebColor("000000"),
OVER = GraphicsUtils.getWebColor("7F7F7F");
public TextFieldPainter() {
}
public TextFieldPainter(boolean fill) {
this.fill = fill;
}
private void paintFieldBackground(SynthContext context, Graphics g, int x, int y, int w, int h) {
w--;
h--;
if (fill) {
g.setColor(Color.WHITE);
g.fillRect(x, y, w, h);
}
Color color;
if ((context.getComponentState() & SynthConstants.MOUSE_OVER) != 0)
color = OVER;
else if ((context.getComponentState() & SynthConstants.DISABLED) != 0)
color = DISABLED;
else if ((context.getComponentState() & SynthConstants.FOCUSED) != 0)
color = FOCUSED;
else
color = NORMAL;
g.setColor(color);
g.drawLine(x, y, x + w, y);
g.drawLine(x, y, x, y + w);
g.drawLine(x + w, y, x + w, y + h);
g.drawLine(x, y + h, x + w, y + h);
}
@Override
public void paintPasswordFieldBackground(SynthContext context, Graphics g, int x, int y, int w, int h) {
paintFieldBackground(context, g, x, y, w, h);
}
@Override
public void paintTextAreaBackground(SynthContext context, Graphics g, int x, int y, int w, int h) {
paintFieldBackground(context, g, x, y, w, h);
}
@Override
public void paintTextFieldBackground(SynthContext context, Graphics g, int x, int y, int w, int h) {
paintFieldBackground(context, g, x, y, w, h);
}
@Override
public void paintTextPaneBackground(SynthContext context, Graphics g, int x, int y, int w, int h) {
paintFieldBackground(context, g, x, y, w, h);
}
@Override
public void paintScrollPaneBackground(SynthContext context, Graphics g, int x, int y, int w, int h) {
paintFieldBackground(context, g, x, y, w, h);
}
}

View File

@ -0,0 +1,384 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* TranslucentPopupFactory.java at 2015-2-1 20:25:38, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.popup;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.Window;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JToolTip;
import javax.swing.JWindow;
import javax.swing.MenuElement;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicComboPopup;
import org.jackhuang.hmcl.laf.scroll.BEScrollBarUI;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
import org.jackhuang.hmcl.laf.WindowTranslucencyHelper;
import org.jackhuang.hmcl.laf.widget.ImageBgPanel;
/**
* 自定义透明背景的弹出工厂实现类.
*
* 本类其实与Swing的UI机制关联不大完全可以独立于L&F使用
*
* @author Jack Jiang(jb2011@163.com), 2012-05-18
* @version 1.0
*/
public class TranslucentPopupFactory extends PopupFactory {
private static final Icon9Factory ICON_9 = new Icon9Factory("popup");
@Override
public Popup getPopup(Component owner, Component contents, int x, int y)
throws IllegalArgumentException {
// A more complete implementation would cache and reuse popups
return new TranslucentPopup(owner, contents, x, y);
}
/**
* 透明背景的Popup实现类.
* <p>
* 本类的大部分代码都是原封不动地参考自Popup父类(JDK版本是1.6_u18版的源码)因为Popup父
* 类中的多数方法都是使用的包内可见性所以没法直接继承像这种不允许第3方自行扩展的情
* 况在Swing标准包里比较少见不知原作者是出于何种考虑无疑这样的类实现是相当的欠缺远 见性但这种情况在LNF里很常见
*/
protected class TranslucentPopup extends Popup {
//copy all from parent class
/**
* The Component representing the Popup.
*/
private Component component;
//copy all from parent class
/**
* Creates a <code>Popup</code> for the Component <code>owner</code>
* containing the Component <code>contents</code>. <code>owner</code> is
* used to determine which <code>Window</code> the new
* <code>Popup</code> will parent the <code>Component</code> the
* <code>Popup</code> creates to. A null <code>owner</code> implies
* there is no valid parent. <code>x</code> and <code>y</code> specify
* the preferred initial location to place the <code>Popup</code> at.
* Based on screen size, or other paramaters, the <code>Popup</code> may
* not display at <code>x</code> and <code>y</code>.
*
* @param owner Component mouse coordinates are relative to, may be null
* @param contents Contents of the Popup
* @param x Initial x screen coordinate
* @param y Initial y screen coordinate
*/
public TranslucentPopup(Component owner, Component contents, int x,
int y) {
this();
if (contents == null)
throw new IllegalArgumentException("Contents must be non-null");
reset(owner, contents, x, y);
}
/**
* Creates a <code>Popup</code>. This is provided for subclasses.
*/
public TranslucentPopup() {
}
/**
* <p>
* Makes the <code>Popup</code> visible. If the <code>Popup</code> is
* currently visible, this has no effect.<br>
*
* 本方法的结构完全copy自父类方法但添加了component.repaint();的调用.
* </p>
*/
@Override
public void show() {
Component c = getComponent();
if (c != null) {
c.setVisible(true);
//此行代码必须要有否则可能是因为没有关闭双缓存getRootPane().
//setUseTrueDoubleBuffering(false)这个方法是包内可见所以本类里没法调用
//而导致界面没有重绘要不就是UI没有绘出来要不就是出现空白的popup没有内容组件
c.repaint();
}
}
/**
* Hides and disposes of the <code>Popup</code>. Once a
* <code>Popup</code> has been disposed you should no longer invoke
* methods on it. A <code>dispose</code>d <code>Popup</code> may be
* reclaimed and later used based on the <code>PopupFactory</code>. As
* such, if you invoke methods on a <code>disposed</code>
* <code>Popup</code>, indeterminate behavior will result.
*/
@Override
public void hide() {
Component c = getComponent();
if (c instanceof JWindow) {
c.hide();
((JWindow) c).getContentPane().removeAll();
}
dispose();
}
/**
* Frees any resources the <code>Popup</code> may be holding onto.
*/
protected void dispose() {
Component c = getComponent();
Window window = SwingUtilities.getWindowAncestor(c);
if (c instanceof JWindow) {
((Window) c).dispose();
c = null;
}
// If our parent is a DefaultFrame, we need to dispose it, too.
if (window instanceof DefaultFrame)
window.dispose();
}
/**
* <p>
* Resets the <code>Popup</code> to an initial state.<br>
*
* 本方法的结构完全copy自父类方法但进行中包括窗口透明用图片实现背景填充等在内的修改.
* </p>
*
* @param owner the owner
* @param contents the contents
* @param ownerX the owner x
* @param ownerY the owner y
*/
protected void reset(Component owner, Component contents, int ownerX, int ownerY) {
if (getComponent() == null)
component = createComponent(owner);
Component c = getComponent();
if (c instanceof JWindow) {
JWindow w = (JWindow) getComponent();
w.setLocation(ownerX, ownerY);
boolean isTooltip = ((JComponent) contents instanceof JToolTip);
//如果contents是BasicComboPopup或其子类那当前就应该是用于下拉框的弹出列表罗
boolean isComboBoxPopup = (contents instanceof BasicComboPopup);
//每像素透明
WindowTranslucencyHelper.setWindowOpaque(w, false);
//内容组件半透明
w.setOpacity(isTooltip ? 1.0f : isComboBoxPopup ? 0.95f : 0.95f);//0.85f : 0.95f);//0.8f : 0.95f);
// component.getContentPane().add(contents, BorderLayout.CENTER);
// contents.invalidate();
// if (component.isVisible())
// {
// // Do not call pack() if window is not visible to
// // avoid early native peer creation
// pack();
// }
//图片填充背景的内容面板
ImageBgPanel imageContentPane = new ImageBgPanel().setN9(
isTooltip
? ICON_9.get("tooltip")
: isComboBoxPopup
?//是下拉框列表则使一个跟JScrollPane一样的背景图好看
BEScrollBarUI.ICON_9.get("scroll_pane_border")
: ICON_9.get("popup")
);
imageContentPane.setLayout(new BorderLayout());
imageContentPane.add(contents, BorderLayout.CENTER);
//为每一个要显示的真正的内容组件加一个空border目的
//是使得父面板的背景图片显示的效果更好
if (contents instanceof JComponent) {
((JComponent) contents).setOpaque(false);
//* ######################################### Bug FIX START ############################################
//* 关于Java Bug 6683775,地址http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6683775解决于java1.6.0_14
//*
//* Bug说明
//* 在java1.6.0_14之前(当然是>=u10版)在设置窗口透明时即调用方法
//* AWTUtilities.setWindowOpaque(component, false)使得窗口透明后再设置位于
//* Windows上的第1层JPanel也为透明时(即JPanel.setOpaque(false))则会出现类似
//* 于很久以前给JPanel设置一个半透明色即alpha小于255时出现的不正确paint情况
//* 直接导致下拉框的弹出列表ui刷新出现混乱根本就不能即时刷新ui一塌糊涂的情况.
//*
//* java1.6.0_14版前如何解决
//* 该Bug 6683775在被官方解决前怎么才能避免出现ui刷新
//* 混乱呢Bug 6683775上的官方回复给出了解决方案JPanel.setDoubleBuffered(false)官方认为
//* 光设置JPanel.setOpaque(false)是不够的还得取消双缓冲才行不过好在官方在u14及以后的版本中
//* 彻底解决了这个问题.
//*
//* 目前BeautyEye L&F中如何解决
//* 为了能在该Bug被解决前即java小于java1.6.0_14版BE LNF也能正常运行只能稍微牺牲一点ui性能
//* 按官方解决方法JPanel.setDoubleBuffered(false)来解决吧.
((JComponent) contents).setDoubleBuffered(false);
//* ######################################### Bug FIX END ##############################################
((JComponent) contents).setBorder(
isTooltip
? BorderFactory.createEmptyBorder(6, 8, 12, 12)//6,8,12,8)
: isComboBoxPopup ? BorderFactory.createEmptyBorder(6, 4, 6, 4)
: BorderFactory.createEmptyBorder(5, 3, 6, 3));//10,2,10,4));//5,5,20,5));
}
//如果BasicComboPopup即表明它应该是ComboBox里的弹出菜单为了使N9
//背景能被完整展现出来则要把combox弹出列表所在的JScrollPane进行透明设置
//因为如果它不被透明设置则本pop的NP图背景就只能显示边缘而且底边有一点被
//挡住不好看另注本JScrollPane在BEComboBoxUI中被设置了一个EmptyBorder所以
//没有在ScrollPaneUI中定认的那个ScrollBorder哦没有那个border的目的就是为了在些使用
//pop的背景撒
if (isComboBoxPopup) {
Component[] cs = ((BasicComboPopup) contents).getComponents();
//该JScrollPane就是contents的第一层子组件里
if (cs != null && cs.length > 0)
//遍历并找出它
for (Component com : cs)
if (com instanceof JScrollPane)
((JScrollPane) com).setOpaque(false);
} //如果是菜单父宿主则所有JMenuItem也设置透明,jb2011 2009-08-29
else if (contents instanceof JPopupMenu) {
MenuElement[] mes = ((JPopupMenu) contents).getSubElements();
for (MenuElement me : mes)
if (me instanceof JMenuItem)
((JMenuItem) me).setOpaque(false);
}
// add the contents to the popup
w.setContentPane(imageContentPane);
// popupWindow.getContentPane().add(p, BorderLayout.CENTER);
// contents.invalidate();
if (w.isVisible())
// Do not call pack() if window is not visible to
// avoid early native peer creation
pack();
}
}
/**
* Causes the <code>Popup</code> to be sized to fit the preferred size
* of the <code>Component</code> it contains.
*/
protected void pack() {
Component c = getComponent();
if (c instanceof Window)
((Window) c).pack();
}
/**
* Returns the <code>Window</code> to use as the parent of the
* <code>Window</code> created for the <code>Popup</code>. This creates
* a new <code>DefaultFrame</code>, if necessary.
*
* @param owner the owner
* @return the parent window
*/
protected Window getParentWindow(Component owner) {
Window window = null;
if (owner instanceof Window)
window = (Window) owner;
else if (owner != null)
window = SwingUtilities.getWindowAncestor(owner);
if (window == null)
window = new DefaultFrame();
return window;
}
/**
* Creates the Component to use as the parent of the <code>Popup</code>.
* The default implementation creates a <code>Window</code>, subclasses
* should override.
*
* @param owner the owner
* @return the component
*/
protected Component createComponent(Component owner) {
if (GraphicsEnvironment.isHeadless())
// Generally not useful, bail.
return null;
return new HeavyWeightWindow(getParentWindow(owner));
}
/**
* Returns the <code>Component</code> returned from
* <code>createComponent</code> that will hold the <code>Popup</code>.
*
* @return the component
*/
protected Component getComponent() {
return component;
}
/**
* Used if no valid Window ancestor of the supplied owner is found.
* <p>
* PopupFactory uses this as a way to know when the Popup shouldn't be
* cached based on the Window.
*/
protected class DefaultFrame extends Frame {
}
/**
* Component used to house window.
*/
protected class HeavyWeightWindow extends JWindow {
/**
* Instantiates a new heavy weight window.
*
* @param parent the parent
*/
public HeavyWeightWindow(Window parent) {
super(parent);
// FIXME: 一个外国朋友用了后在此项被设置成false的情况下Popup里的JTextField不能编辑了
setFocusableWindowState(true);
setName("###overrideRedirect###");
// Popups are typically transient and most likely won't benefit
// from true double buffering. Turn it off here.
// getRootPane().setUseTrueDoubleBuffering(false);//本方法不能在包外被调用
// Try to set "always-on-top" for the popup window.
// Applets usually don't have sufficient permissions to do it.
// In this case simply ignore the exception.
try {
setAlwaysOnTop(true);
} catch (SecurityException se) {
// setAlwaysOnTop is restricted,
// the exception is ignored
}
}
@Override
public void update(Graphics g) {
paint(g);
}
@Override
public void show() {
this.pack();
super.show();
}
}
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.popup;
import javax.swing.PopupFactory;
public class __UI__ {
public static PopupFactory popupFactoryDIY = new TranslucentPopupFactory();
public static void uiImpl() {
PopupFactory.setSharedInstance(popupFactoryDIY);
}
}

View File

@ -0,0 +1,281 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEProgressBarUI.java at 2015-2-1 20:25:39, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.progress;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import javax.swing.JComponent;
import javax.swing.JProgressBar;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicProgressBarUI;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
import org.jackhuang.hmcl.laf.utils.MySwingUtilities2;
import org.jackhuang.hmcl.laf.utils.WinUtils;
import org.jb2011.ninepatch4j.NinePatch;
/**
* 进度条的UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
* @see com.sun.java.swing.plaf.windows.WindowsProgressBarUI
*/
public class BEProgressBarUI extends BasicProgressBarUI
implements org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported {
private static final Icon9Factory ICON_9 = new Icon9Factory("progress_bar");
public static ComponentUI createUI(JComponent x) {
return new BEProgressBarUI();
}
/**
* 是否使用父类的绘制实现方法true表示是.
* <p>
* 因为在BE LNF中进度条和背景都是使用N9图没法通过设置JProgressBar的背景色和前景
* 色来控制进度条的颜色本方法的目的就是当用户设置了进度条的Background或Foreground 时告之本实现类不使用BE
* LNF中默认的N9图填充绘制而改用父类中的方法父类中的方法 就可以支持颜色的设置罗只是丑点但总归是能适应用户的需求场景要求其实用户完全可以
* 通过JProgressBar.setUI(new MetalProgressBar())方式来自定义进度的UI哦.
*
* @return true, if is use parent paint
*/
@Override
public boolean isUseParentPaint() {
return progressBar != null
&& (!(progressBar.getForeground() instanceof UIResource)
|| !(progressBar.getBackground() instanceof UIResource));
}
/**
* 绘制普通进度条的方法.
* All purpose paint method that should do the right thing for almost all
* linear, determinate progress bars. By setting a few values in the
* defaults table, things should work just fine to paint your progress bar.
* Naturally, override this if you are making a circular or semi-circular
* progress bar.
*
* @param g the g
* @param c the c
* @see #paintIndeterminate
* @see javax.swing.plaf.basic.BasicProgressBarUI#paintDeterminate(java.awt.Graphics, javax.swing.JComponent)
* @since 1.4
*/
@Override
protected void paintDeterminate(Graphics g, JComponent c) {
if (!(g instanceof Graphics2D))
return;
//* 如果用户作了自定义颜色设置则使用父类方法来实现绘制否则BE LNF中没法支持这些设置哦
if (isUseParentPaint()) {
super.paintDeterminate(g, c);
return;
}
Insets b = progressBar.getInsets(); // area for border
int barRectWidth = progressBar.getWidth() - (b.right + b.left);
int barRectHeight = progressBar.getHeight() - (b.top + b.bottom);
//* add by Jack Jiang 2012-06-20 START
//绘制进度条的背景
paintProgressBarBgImpl(progressBar.getOrientation() == JProgressBar.HORIZONTAL,
g, b, barRectWidth, barRectHeight);
//* add by Jack Jiang 2012-06-20 END
if (barRectWidth <= 0 || barRectHeight <= 0)
return;
int amountFull = getAmountFull(b, barRectWidth, barRectHeight);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(progressBar.getForeground());//在BE LNF中本属性设置目前没有意义哦因为用的都是n9图
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
if (WinUtils.isLeftToRight(c))
paintProgressBarContentImpl(true, g, b.left, b.top,
amountFull, barRectHeight, -1);
// TODO 以下代码未经测试
else
paintProgressBarContentImpl(true, g, barRectWidth + b.left, b.top,
barRectWidth + b.left - amountFull, barRectHeight, -1);
else // VERTICAL
paintProgressBarContentImpl(false, g, b.left, b.top + barRectHeight - amountFull,
barRectWidth, amountFull, barRectHeight);
// Deal with possible text painting
if (progressBar.isStringPainted())
paintString(g, b.left, b.top, barRectWidth, barRectHeight, amountFull, b);
}
//绘制无穷进度条的方法
/**
* All purpose paint method that should do the right thing for all linear
* bouncing-box progress bars. Override this if you are making another kind
* of progress bar.
*
* @param g the g
* @param c the c
* @see #paintDeterminate
* @since 1.4
* @see javax.swing.plaf.basic.BasicProgressBarUI#paintIndeterminate(java.awt.Graphics, javax.swing.JComponent)
*/
@Override
protected void paintIndeterminate(Graphics g, JComponent c) {
if (!(g instanceof Graphics2D))
return;
//* 如果用户作了自定义颜色设置则使用父类方法来实现绘制否则BE LNF中没法支持这些设置哦
if (isUseParentPaint()) {
super.paintIndeterminate(g, c);
return;
}
Insets b = progressBar.getInsets(); // area for border
int barRectWidth = progressBar.getWidth() - (b.right + b.left);
int barRectHeight = progressBar.getHeight() - (b.top + b.bottom);
if (barRectWidth <= 0 || barRectHeight <= 0)
return;
//* add by Jack Jiang 2012-06-20 START
//绘制进度条的背景
paintProgressBarBgImpl(progressBar.getOrientation() == JProgressBar.HORIZONTAL, g, b, barRectWidth, barRectHeight);
//* add by Jack Jiang 2012-06-20 END
Graphics2D g2 = (Graphics2D) g;
// Paint the bouncing box.
boxRect = getBox(boxRect);
if (boxRect != null) {
g2.setColor(progressBar.getForeground());//BE LNF中目前本颜色设置无意义哦因使用的都是N9图
//由Jack Jiang修改
// g2.fillRect(boxRect.x, boxRect.y, boxRect.width, boxRect.height);
paintProgressBarContentImpl(progressBar.getOrientation() == JProgressBar.HORIZONTAL,
g, boxRect.x, boxRect.y, boxRect.width, boxRect.height, boxRect.height);//水平时最后一个参数无意义哦
}
// Deal with possible text painting
if (progressBar.isStringPainted())
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
paintString(g2, b.left, b.top, barRectWidth, barRectHeight, boxRect.x, boxRect.width, b);
else
paintString(g2, b.left, b.top, barRectWidth, barRectHeight, boxRect.y, boxRect.height, b);
}
//* add by Jack Jiang
/**
* 进度条当前值的绘制实现方法.
*
* @param isHorizontal true表示水平进度条否则表示垂直进度条
* @param g the g
* @param x the x
* @param y the y
* @param amountFull the amount full
* @param barContentRectHeight the bar content rect height
* @param barSumHeightForVertival 本参数只在垂直进度条时有意义目的是为了在当前值很
* 小的情况下为了达到N9图最小绘制高度时作修正时需要
*/
protected void paintProgressBarContentImpl(boolean isHorizontal,
Graphics g, int x, int y, int amountFull, int barContentRectHeight,
int barSumHeightForVertival) {
NinePatch np;
//当前的进度条内容.9.png图片的边缘非填充部分是17像素如果要
//填充的总宽度小于此则会出现NinePatch填充算法无法解决的填充
//以下判断将在总宽度小于此值时强制设置成最小宽度
final int n9min = 17;// TODO 14是相关于.9.png图片的最小填充宽度的最好用常量实现
if (isHorizontal) {
//如果最小填充长度小于n9图的最小长度最设定为最小长度否则N9的填充会很难看哦
if (amountFull > 0 && amountFull < n9min)
amountFull = n9min;
np = ICON_9.get("green");
} else {
//如果最小填充长度小于n9图的最小长度最设定为最小长度否则N9的填充会很难看哦
if (barContentRectHeight > 0 && barContentRectHeight < n9min) {
y = barSumHeightForVertival - n9min;
barContentRectHeight = n9min;
}
np = ICON_9.get("blur_vertical");
}
//开始绘制N9图
np.draw((Graphics2D) g, x, y, amountFull, barContentRectHeight);
}
//* add by Jack Jiang
/**
* 进度条背景填充实现方法.
*
* @param isHorizontal the is horizontal
* @param g the g
* @param b the b
* @param barRectWidth the bar rect width
* @param barRectHeight the bar rect height
*/
protected void paintProgressBarBgImpl(boolean isHorizontal, Graphics g, Insets b, int barRectWidth, int barRectHeight) {
ICON_9.getWithHorizontal("bg", isHorizontal)
.draw((Graphics2D) g, b.left, b.top, barRectWidth, barRectHeight);
}
/**
* Paints the progress string.
*
* @param g Graphics used for drawing.
* @param x x location of bounding box
* @param y y location of bounding box
* @param width width of bounding box
* @param height height of bounding box
* @param fillStart start location, in x or y depending on orientation, of
* the filled portion of the progress bar.
* @param amountFull size of the fill region, either width or height
* depending upon orientation.
* @param b Insets of the progress bar.
*/
private void paintString(Graphics g, int x, int y, int width, int height,
int fillStart, int amountFull, Insets b) {
if (!(g instanceof Graphics2D))
return;
Graphics2D g2 = (Graphics2D) g;
String progressString = progressBar.getString();
g2.setFont(progressBar.getFont());
Point renderLocation = getStringPlacement(g2, progressString,
x, y, width, height);
Rectangle oldClip = g2.getClipBounds();
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
g2.setColor(getSelectionBackground());
MySwingUtilities2.drawString(progressBar, g2, progressString,
renderLocation.x, renderLocation.y);
g2.setColor(getSelectionForeground());
g2.clipRect(fillStart, y, amountFull, height);
MySwingUtilities2.drawString(progressBar, g2, progressString,
renderLocation.x, renderLocation.y);
} else { // VERTICAL
g2.setColor(getSelectionBackground());
AffineTransform rotate
= AffineTransform.getRotateInstance(Math.PI / 2);
g2.setFont(progressBar.getFont().deriveFont(rotate));
renderLocation = getStringPlacement(g2, progressString,
x, y, width, height);
MySwingUtilities2.drawString(progressBar, g2, progressString,
renderLocation.x, renderLocation.y);
g2.setColor(getSelectionForeground());
g2.clipRect(x, fillStart, width, amountFull);
MySwingUtilities2.drawString(progressBar, g2, progressString,
renderLocation.x, renderLocation.y);
}
g2.setClip(oldClip);
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.progress;
import javax.swing.BorderFactory;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
public static void uiImpl() {
put("ProgressBar.background", BeautyEyeLNFHelper.commonBackgroundColor);
put("ProgressBar.selectionForeground", BeautyEyeLNFHelper.commonBackgroundColor);
// 此属性决定水平进度条的默认最小大小15是相关于.9.png图片的最小填充
// 高度或长度的(小于此高度则NinePatch算法无法解决而很难看)
putDim("ProgressBar.horizontalSize", 146, 15); // 默认是146,12
putDim("ProgressBar.verticalSize", 15, 146); // 默认是12,146
put("ProgressBar.border", BorderFactory.createEmptyBorder(0, 0, 0, 0));
put("ProgressBarUI", BEProgressBarUI.class);
}
}

View File

@ -0,0 +1,44 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.laf.radio$cb_btn;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.metal.MetalCheckBoxUI;
/**
*
* @author huang
*/
public class BECheckBoxUI extends MetalCheckBoxUI {
private static final BECheckBoxUI INSTANCE = new BECheckBoxUI();
public static ComponentUI createUI(JComponent b) {
return INSTANCE;
}
@Override
public void installDefaults(AbstractButton b) {
super.installDefaults(b);
LookAndFeel.installProperty(b, "opaque", false);
}
}

View File

@ -0,0 +1,45 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.laf.radio$cb_btn;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.metal.MetalRadioButtonUI;
/**
*
* @author huang
*/
public class BERadioButtonUI extends MetalRadioButtonUI {
private static final BERadioButtonUI INSTANCE = new BERadioButtonUI();
public static ComponentUI createUI(JComponent b) {
return INSTANCE;
}
@Override
public void installDefaults(AbstractButton b) {
super.installDefaults(b);
LookAndFeel.installProperty(b, "opaque", false);
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.radio$cb_btn;
import java.awt.Component;
import java.awt.Graphics;
import java.io.Serializable;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.IconFactory;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
private static final IconFactory RADIO = new IconFactory("radio");
private static final IconFactory CHECK = new IconFactory("check");
public static void uiImpl() {
putInsets("CheckBox.margin", 4, 3, 4, 3);
put("CheckBox.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("CheckBox.background", BeautyEyeLNFHelper.commonBackgroundColor);
put("CheckBoxUI", BECheckBoxUI.class);
putInsets("RadioButton.margin", 4, 3, 4, 3); // 2, 2, 2, 2
put("RadioButton.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("RadioButton.background", BeautyEyeLNFHelper.commonBackgroundColor);
put("RadioButtonUI", BERadioButtonUI.class);
UIManager.put("RadioButton.icon", new IconFactoryIcon(RADIO));
UIManager.put("CheckBox.icon", new IconFactoryIcon(CHECK));
// 衬距设定
putInsets("RadioButton.margin", 1, 1, 1, 1); // 2, 2, 2, 2
putInsets("CheckBox.margin", 1, 1, 1, 1); // 2, 2, 2, 2
}
/**
* @see com.sun.java.swing.plaf.windows.WindowsIconFactory
* @see com.sun.java.swing.plaf.windows.WindowsIconFactory.CheckBoxIcon
* @see com.sun.java.swing.plaf.windows.WindowsIconFactory.RadioBoxIcon
*/
private static class IconFactoryIcon implements Icon, Serializable {
IconFactory icon;
public IconFactoryIcon(IconFactory icon) {
this.icon = icon;
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
JToggleButton cb = (JToggleButton) c;
ButtonModel model = cb.getModel();
g.drawImage(icon.get(model.isSelected() ? "" : "unchecked",
model.isEnabled() ? (model.isPressed() ? "pressed" : (model.isRollover() ? "over" : "normal")) : "disabled").getImage(),
x, y, null);
}
@Override
public int getIconWidth() {
return 24;
}
@Override
public int getIconHeight() {
return 24;
}
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* beautyeye.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.resources;
import java.util.ListResourceBundle;
public final class beautyeye extends ListResourceBundle
{
protected final Object[][] getContents()
{
return new Object[][] {
{ "BETitlePane.setupButtonText", "Setup " },
{ "BETitlePane.titleMenuToolTipText", "Window operation." },
{ "BETitlePane.closeButtonToolTipext", "Close" },
{ "BETitlePane.iconifyButtonToolTipText", "Minimize" },
{ "BETitlePane.toggleButtonToolTipText", "Maximize" },
{ "BETitlePane.iconifyButtonText", "Minimize(N)" },
{ "BETitlePane.restoreButtonText", "Restore(R)" },
{ "BETitlePane.maximizeButtonText", "Maximized(X)" },
};
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* beautyeye_zh_CN.java at 2015-2-1 20:25:41, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.resources;
import java.util.ListResourceBundle;
public final class beautyeye_zh_CN extends ListResourceBundle
{
protected final Object[][] getContents()
{
return new Object[][] {
{ "BETitlePane.setupButtonText", "\u8bbe\u7f6e " },
{ "BETitlePane.titleMenuToolTipText", "\u7a97\u53e3\u76f8\u5173\u64cd\u4f5c." },
{ "BETitlePane.closeButtonToolTipext", "\u5173\u95ed" },
{ "BETitlePane.iconifyButtonToolTipText", "\u6700\u5c0f\u5316" },
{ "BETitlePane.toggleButtonToolTipText", "\u6700\u5927\u5316" },
{ "BETitlePane.iconifyButtonText", "\u6700\u5c0f\u5316(N)" },
{ "BETitlePane.restoreButtonText", "\u8fd8\u539f(R)" },
{ "BETitlePane.maximizeButtonText", "\u6700\u5927\u5316(X)" },
};
}
}

View File

@ -0,0 +1,264 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEScrollBarUI.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.scroll;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Rectangle;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JScrollBar;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicArrowButton;
import javax.swing.plaf.basic.BasicScrollBarUI;
import org.jackhuang.hmcl.laf.BEUtils;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
import org.jb2011.ninepatch4j.NinePatch;
/**
* 本类是滚动条的UI实现.
*
* 滚动条的两端箭头按钮参考自xp主题的实现未作修改因而这部分逻辑代码与WindowsScrollBarUI中是完全一样的.
*
* @author Jack Jiang(jb2011@163.com), 2009-09-01
* @version 1.0
* @see com.sun.java.swing.plaf.windows.WindowsScrollBarUI
*/
public class BEScrollBarUI extends BasicScrollBarUI {
public static final Icon9Factory ICON_9 = new Icon9Factory("scroll_bar");
public static ComponentUI createUI(JComponent c) {
return new BEScrollBarUI();
}
@Override
protected JButton createDecreaseButton(int orientation) {
return new BEArrowButton(orientation,
UIManager.getColor("ScrollBar.thumb"),
UIManager.getColor("ScrollBar.thumbShadow"),
UIManager.getColor("ScrollBar.thumbDarkShadow"),
UIManager.getColor("ScrollBar.thumbHighlight"));
}
@Override
protected JButton createIncreaseButton(int orientation) {
return new BEArrowButton(orientation,
UIManager.getColor("ScrollBar.thumb"),
UIManager.getColor("ScrollBar.thumbShadow"),
UIManager.getColor("ScrollBar.thumbDarkShadow"),
UIManager.getColor("ScrollBar.thumbHighlight"));
}
/**
* WindowsArrowButton is used for the buttons to position the document
* up/down. It differs from BasicArrowButton in that the preferred size is
* always a square.
*/
protected class BEArrowButton extends BasicArrowButton {
/**
* Instantiates a new windows arrow button.
*
* @param direction the direction
* @param background the background
* @param shadow the shadow
* @param darkShadow the dark shadow
* @param highlight the highlight
*/
public BEArrowButton(int direction, Color background, Color shadow,
Color darkShadow, Color highlight) {
super(direction, background, shadow, darkShadow, highlight);
}
public BEArrowButton(int direction) {
super(direction);
}
@Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
String id = "arrow_";
switch (direction) {
case NORTH:
id += "top";
break;
case SOUTH:
id += "bottom";
break;
case WEST:
id += "left";
break;
case EAST:
id += "right";
break;
}
ICON_9.get(id, getModel().isRollover() ? "rollover" : "")
.draw(g2, 0, 0, getWidth(), getHeight());
}
@Override
public Dimension getPreferredSize() {
int size = 16;
if (scrollbar != null) {
switch (scrollbar.getOrientation()) {
case JScrollBar.VERTICAL:
size = scrollbar.getWidth();
break;
case JScrollBar.HORIZONTAL:
size = scrollbar.getHeight();
break;
}
size = Math.max(size, 5);
}
return new Dimension(size, size);
}
}
//----------------------------------------------------------------------------------- END
//----------------------------------------------------------------------------------- 本次改造的主体部分
@Override
protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) {
if (c == null || g == null)
return;
Graphics2D g2 = (Graphics2D) g;
Paint oldp = g2.getPaint();
int w = trackBounds.width;
int h = trackBounds.height;
int x = trackBounds.x;
int y = trackBounds.y;
if (this.scrollbar.getOrientation() == JScrollBar.VERTICAL) {
// //1/2处渐变
// GradientPaint gp = new GradientPaint(x, y
// , GraphicHandler.getColor(trackColor,-15,-15,-15), w/2, y,trackColor);
// g2.setPaint(gp);
// g2.fillRect(x, y, w/2, h);
//
// g2.setPaint(oldp);
// g2.setColor(trackColor);
// g2.fillRect(w/2, y, w/2, h);
//** 简洁版轨迹实现
int hhhWidth = 5;
int px = (w - hhhWidth) / 2;
int delta = 50;
//第1条
g2.setColor(new Color(150 + delta, 151 + delta, 146 + delta));
g2.drawLine(px + 0, y + 10, px + 0, y + h - 10);
//第2条
g2.setColor(new Color(160 + delta, 160 + delta, 162 + delta));
g2.drawLine(px + 1, y + 10, px + 1, y + h - 10);
//第3条
g2.setColor(new Color(163 + delta, 162 + delta, 167 + delta));
g2.drawLine(px + 2, y + 10, px + 2, y + h - 10);
//第4条
g2.setColor(new Color(162 + delta, 162 + delta, 162 + delta));
g2.drawLine(px + 3, y + 10, px + 3, y + h - 10);
//第5条
g2.setColor(new Color(150 + delta, 150 + delta, 150 + delta));
g2.drawLine(px + 4, y + 10, px + 4, y + h - 10);
} else {
//1/2处渐变
// GradientPaint gp = new GradientPaint(x, y
// , GraphicHandler.getColor(trackColor,-15,-15,-15), x, h/2,trackColor);
// g2.setPaint(gp);
// g2.fillRect(x, y, w, h/2);
//
// g2.setPaint(oldp);
// g2.setColor(trackColor);
// g2.fillRect(x, h/2, w, h);
//** 简洁版轨迹实现
int hhhWidth = 5;
int py = (h - hhhWidth) / 2;
int delta = 50;
//第1条
g2.setColor(new Color(150 + delta, 151 + delta, 146 + delta));
g2.drawLine(x + 10, py + 0, x + w - 10, py + 0);
//第2条
g2.setColor(new Color(160 + delta, 160 + delta, 162 + delta));
g2.drawLine(x + 10, py + 1, x + w - 10, py + 1);
//第3条
g2.setColor(new Color(163 + delta, 162 + delta, 167 + delta));
g2.drawLine(x + 10, py + 2, x + w - 10, py + 2);
//第4条
g2.setColor(new Color(162 + delta, 162 + delta, 162 + delta));
g2.drawLine(x + 10, py + 3, x + w - 10, py + 3);
//第5条
g2.setColor(new Color(150 + delta, 150 + delta, 150 + delta));
g2.drawLine(x + 10, py + 4, x + w - 10, py + 4);
}
}
/**
* 滚动条绘制.
*/
@Override
protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
if (thumbBounds.isEmpty() || !scrollbar.isEnabled())
return;
Graphics2D g2 = (Graphics2D) g;
int w = thumbBounds.width - 4;
int h = thumbBounds.height - 4;
g2.translate(thumbBounds.x + 2, thumbBounds.y + 2);
// g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
BEUtils.setAntiAliasing(g2, true);
//防止thunmb的最小高度比图片的最小高度还要小这样在绘制时就会出问题
//起实目前没还没有办法很好解决因为即使在这里作处理但是thumb本身
//还是那么小所以绘图还是会有问题但起码在不拖动时看起来是正常的以后再解决吧
if (this.scrollbar.getOrientation() == JScrollBar.VERTICAL) {
NinePatch np = ICON_9.getWithScrollState("vertical", isDragging, isThumbRollover());
if (h < np.getHeight())
paintThumbIfSoSmall(g2, 0, 0, w, h);
else
np.draw(g2, 0, 0, w, h);
} else {
NinePatch np = ICON_9.getWithScrollState("horizontal", isDragging, isThumbRollover());
if (w < np.getWidth())
paintThumbIfSoSmall(g2, 0, 0, w, h);
else
np.draw(g2, 0, 0, w, h);
}
//如果滚动行宽度小于NP图的最小宽度时则交给此方法绘制否则NP图的填充将出现虚绘而影响滚动条的体验哦
g2.translate(-thumbBounds.x, -thumbBounds.y);
// g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
BEUtils.setAntiAliasing(g2, false);
}
//----------------------------------------------------------------------------------- END
/**
* 如果滚动条非常小小到小于NP图的最小大小时调用此方法实现滚动条的精确绘制.
*
* @see javax.swing.plaf.basic.BasicScrollBarUI#paintThumb(java.awt.Graphics, javax.swing.JComponent, java.awt.Rectangle)
*/
protected void paintThumbIfSoSmall(Graphics2D g2, int x, int y, int w, int h) {
final int NORMAL_ARC = 6;//定义圆角直径
//如果w或h太小时则就不绘制圆角了(直角即可)要不然就没法绘全圆角而很难看
int arc = ((w <= NORMAL_ARC || h <= NORMAL_ARC) ? 0 : NORMAL_ARC);
g2.setColor(thumbDarkShadowColor);
g2.drawRoundRect(x, y, w - 1, h - 1, arc, arc);//画滚动条的外层
g2.setColor(thumbColor);
g2.fillRoundRect(x + 1, y + 1, w - 2, h - 2, arc, arc);//填充滚动条的内层
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEScrollPaneUI.java at 2015-2-1 20:25:39, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.scroll;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicScrollPaneUI;
/**
* 滚动面板的UI实现类.
*
* @author Jack Jiang(jb2011@163.com
*/
public class BEScrollPaneUI extends BasicScrollPaneUI {
public static ComponentUI createUI(JComponent x) {
return new BEScrollPaneUI();
}
@Override
protected void installDefaults(JScrollPane scrollpane) {
super.installDefaults(scrollpane);
// /* ~~注ScrollPane.opaque这个属性是jb2011自已加的目的是控制滚动面板及其Viewport的透明性 */
// scrollpane.setOpaque(UIManager.getBoolean("ScrollPane.opaque"));
// scrollpane.getViewport().setOpaque(UIManager.getBoolean("ScrollPane.opaque"));
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* ScrollPaneBorder.java at 2015-2-1 20:25:41, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.scroll;
import java.awt.Insets;
import org.jackhuang.hmcl.laf.widget.border.NinePatchBorder;
/**
* 滚动面板默认Border的实现类.
*
* @author Jack Jiang(jb2011@163.com)
*/
public class ScrollPaneBorder extends NinePatchBorder {
public ScrollPaneBorder() {
super(new Insets(6, 6, 8, 6),
BEScrollBarUI.ICON_9.get("scroll_pane_border"));
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.scroll;
import java.awt.Color;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
public static void uiImpl() {
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 视口的相关ui值设定
put("Viewport.background", BeautyEyeLNFHelper.commonBackgroundColor);
put("Viewport.foreground", BeautyEyeLNFHelper.commonForegroundColor);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JScrollPane的相关ui值设定
put("ScrollPane.border", new ScrollPaneBorder()); // 0, 0, 0, 0
// 不能设置alpha通道小于255的透明颜色否则会出现无法重paint的问题
put("ScrollPane.background", Color.white);//cc));
put("ScrollPane.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("ScrollPaneUI", BEScrollPaneUI.class);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JScrollPane的滚动条相关ui值设定
put("ScrollBar.thumb", BeautyEyeLNFHelper.commonBackgroundColor);
put("ScrollBar.foreground", BeautyEyeLNFHelper.commonForegroundColor);
putColor("ScrollBar.background", 250, 250, 250);
putColor("ScrollBar.trackForeground", 250, 250, 250);
putColor("scrollbar", 250, 250, 250);
put("ScrollBarUI", BEScrollBarUI.class);
// /* ~~注这个属性是jb2011自已加的目的是控制滚动面板及其Viewport的透明性 */
// //设置成透明是为了让BE LNF中它的N9图实现的border能展现出图片背景来好看一点
// put("ScrollPane.opaque", false);
}
}

View File

@ -0,0 +1,46 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.laf.separator;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.LookAndFeel;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.PanelUI;
import javax.swing.plaf.basic.BasicPanelUI;
/**
*
* @author huang
*/
public class BEPanelUI extends BasicPanelUI {
// Shared UI object
private static PanelUI panelUI;
public static ComponentUI createUI(JComponent c) {
if (panelUI == null)
panelUI = new BEPanelUI();
return panelUI;
}
@Override
protected void installDefaults(JPanel p) {
LookAndFeel.installProperty(p, "opaque", false);
}
}

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BESeparatorUI.java at 2015-2-1 20:25:39, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.separator;
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import javax.swing.JComponent;
import javax.swing.JSeparator;
import javax.swing.LookAndFeel;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSeparatorUI;
/**
* Separator外观实现类.
* <p>
*
* @author Jack Jiang(jb2011@163.com), 2012-11-05
* @version 1.0
*/
public class BESeparatorUI extends BasicSeparatorUI {
public static ComponentUI createUI(JComponent c) {
return new BESeparatorUI();
}
@Override
protected void installDefaults(JSeparator s) {
LookAndFeel.installColors(s, "Separator.background", "Separator.foreground");
LookAndFeel.installProperty(s, "opaque", Boolean.FALSE);
}
@Override
public void paint(Graphics g, JComponent c) {
//** 绘制border的底线
//虚线样式
Stroke oldStroke = ((Graphics2D) g).getStroke();
Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0);//实线空白
((Graphics2D) g).setStroke(sroke);//
// super.paint(g, c);
Dimension s = c.getSize();
if (((JSeparator) c).getOrientation() == JSeparator.VERTICAL) {
// System.out.println("c.getBackground()c.getBackground()c.getBackground()="+c.getBackground());
g.setColor(c.getForeground());
g.drawLine(0, 0, 0, s.height);
g.setColor(c.getBackground());
g.drawLine(1, 0, 1, s.height);
} else // HORIZONTAL
{
g.setColor(c.getForeground());
g.drawLine(0, 0, s.width, 0);
g.setColor(c.getBackground());
g.drawLine(0, 1, s.width, 1);
}
((Graphics2D) g).setStroke(oldStroke);
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.separator;
import java.awt.Color;
import javax.swing.UIManager;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.IconFactory;
import org.jackhuang.hmcl.laf.utils.UI;
import org.jackhuang.hmcl.laf.widget.border.BEDashedRoundRecBorder;
/**
* 各种未归类的UI属性设置实现类. 本类中的各种属性日后可能会移入相应的各独立组件的UI包.
*
* @author Jack Jiang
* @version 1.1
*/
public class __UI__ extends UI {
private static final IconFactory ICON = new IconFactory("option_pane");
public static void uiImpl() {
put("control", BeautyEyeLNFHelper.commonBackgroundColor);
put("Separator.foreground", new Color(180, 180, 180));
put("ToolTip.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("Separator.background", Color.white);
put("Panel.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("Panel.background", BeautyEyeLNFHelper.commonBackgroundColor);
put("PanelUI", BEPanelUI.class);
put("Label.foreground", BeautyEyeLNFHelper.commonForegroundColor);
//put("Label.background", BeautyEyeLNFHelper.commonBackgroundColor);
put("ColorChooser.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("ColorChooser.background", BeautyEyeLNFHelper.commonBackgroundColor);
put("ColorChooser.swatchesDefaultRecentColor", BeautyEyeLNFHelper.commonBackgroundColor);
putColor("TitledBorder.titleColor", 58, 135, 173); // TitleBorder的标题颜色
// TitledBorder的默认border实现windows LNF中默认是圆色灰色实线距形
put("TitledBorder.border", new BEDashedRoundRecBorder(BeautyEyeLNFHelper.commonFocusedBorderColor));
// UIManager.put("OptionPaneUI",org.jb2011.lnf.windows2.ch3.NLOptionPaneUI.class.getName());
//** Ui里的实现逻辑此属性为true时将导致JOptionPane里的各按钮按BasicOptionPaneUI里设定的Insets进行
//** UI展现当按钮数<=2时使用的Insets=new Instes(2,8,2,8)否则使用new Instes(2,4,2,4)
//** 这样的逻辑下BeautyEye L&F实现里会使得按钮高度缩小而不好看所以要关闭此属性
put("OptionPane.setButtonMargin", false);
put("OptionPane.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("OptionPane.background", BeautyEyeLNFHelper.commonBackgroundColor);
UIManager.put("OptionPane.questionIcon", ICON.get("question"));
UIManager.put("OptionPane.warningIcon", ICON.get("warn"));
UIManager.put("OptionPane.informationIcon", ICON.get("info"));
UIManager.put("OptionPane.errorIcon", ICON.get("error"));
put("SeparatorUI", BESeparatorUI.class);
}
}

View File

@ -0,0 +1,158 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BESliderUI.java at 2015-2-1 20:25:38, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.slider;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JSlider;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSliderUI;
import org.jackhuang.hmcl.laf.BEUtils;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
import org.jackhuang.hmcl.laf.utils.IconFactory;
/**
* JSlider的ui实现类.
*
* @author Jack Jiang(jb2011@163.com)
* @version 1.0
*
* @see com.sun.java.swing.plaf.windows.WindowsComboBoxUI
*/
public class BESliderUI extends BasicSliderUI {
private static final Icon9Factory ICON_9 = new Icon9Factory("slider_track");
private static final IconFactory ICON = new IconFactory("slider");
/**
* 水平Slider的Thumb高度.
*/
protected final int THUMB_HEIGHT_HORIZONAL = 7;// TODO 此属性可提取为Ui属性方便以后配置大小应是NP图的最小高度最大值得看JSlider的高度了
/**
* 垂直Slider的Thumb宽度.
*/
protected final int THUMB_WIDTH_VERTICAL = 7;// TODO 此属性可提取为Ui属性方便以后配置大小应是NP图的最小高度最大值得看JSlider的高度了
public BESliderUI(JSlider b) {
super(b);
}
public static ComponentUI createUI(JComponent b) {
return new BESliderUI((JSlider) b);
}
@Override
public void paintTrack(Graphics g) {
Rectangle trackBounds = trackRect;
if (slider.getOrientation() == JSlider.HORIZONTAL) {
int cy = (trackBounds.height / 2) - 2;
int cw = trackBounds.width;
g.translate(trackBounds.x, trackBounds.y + cy);
//轨道背景
ICON_9.getWithEnabled("", slider.isEnabled())
.draw((Graphics2D) g, 0, 0, cw, THUMB_HEIGHT_HORIZONAL);
//轨道填充到当前刻度值处
ICON_9.getWithEnabled("foreground", slider.isEnabled())
.draw((Graphics2D) g, 0, 0, thumbRect.x, THUMB_HEIGHT_HORIZONAL);
g.translate(-trackBounds.x, -(trackBounds.y + cy));
} else {
int cx = (trackBounds.width / 2) - 2;
int ch = trackBounds.height;
g.translate(trackBounds.x + cx, trackBounds.y);
//轨道背景
ICON_9.getWithEnabled("vertical", slider.isEnabled())
.draw((Graphics2D) g, 0, 0, THUMB_WIDTH_VERTICAL, ch);
//轨道填充到当前刻度值处
// TODO BUG当前有个bug即在SwingSets2演示中当thumb高度较小时轨道半圆形被画出这可能父类中thumbRect中计算有部碮同有时间再研究吧官方以后版本或许能解决哦
ICON_9.getWithEnabled("vertical_foreground", slider.isEnabled())
.draw((Graphics2D) g, 0, thumbRect.y, THUMB_WIDTH_VERTICAL, ch - thumbRect.y);
g.translate(-(trackBounds.x + cx), -trackBounds.y);
}
}
@Override
public void paintFocus(Graphics g) {
g.setColor(getFocusColor());
BEUtils.drawDashedRect(g, focusRect.x, focusRect.y,
focusRect.width, focusRect.height);
}
/**
* {@inheritDoc}
*
* @see javax.swing.plaf.basic.BasicSliderUI#paintThumb(java.awt.Graphics)
*/
@Override
public void paintThumb(Graphics g) {
Rectangle knobBounds = thumbRect;
int w = knobBounds.width;
int h = knobBounds.height;
g.translate(knobBounds.x, knobBounds.y);
if (slider.isEnabled())
g.setColor(slider.getBackground());
else
g.setColor(slider.getBackground().darker());
g.drawImage(ICON.get(isPaintNoTriangleThumb() ? "notriangle" : "",
slider.getOrientation() == JSlider.HORIZONTAL ? "" : "vertical",
slider.isEnabled() ? "" : "disabled").getImage(), 0, 0, null);
g.translate(-knobBounds.x, -knobBounds.y);
}
/**
* Checks if is paint no triangle thumb.
* 该thumb是否是无3角箭头的样式true表示无3解箭头即圆形thumbfalse表示有3角箭头样式
*
* @return true, if is paint no trangle thumb
*/
protected boolean isPaintNoTriangleThumb() {
Boolean paintThumbArrowShape = (Boolean) slider
.getClientProperty("Slider.paintThumbArrowShape");
//不绘制有箭头标识的thumb样式(即普通圆形thumb)
return !slider.getPaintTicks() && paintThumbArrowShape == null
|| Boolean.FALSE.equals(paintThumbArrowShape);
}
/**
* {@inheritDoc}
*
* @see javax.swing.plaf.basic.BasicSliderUI#getThumbSize()
*/
@Override
protected Dimension getThumbSize() {
boolean isPaintNoTrangle = isPaintNoTriangleThumb();
Dimension size = new Dimension();
if (slider.getOrientation() == JSlider.VERTICAL) {
size.width = 17;//20;
size.height = isPaintNoTrangle ? 16 : 12;//14;
} else {
size.width = isPaintNoTrangle ? 16 : 12;//14;
size.height = 17;//20;
}
return size;
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:39, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.slider;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
public static void uiImpl() {
put("Slider.background", BeautyEyeLNFHelper.commonBackgroundColor);
//JSlider的刻度线绘制颜色
putColor("Slider.tickColor", 154, 154, 154);
put("Slider.foreground", BeautyEyeLNFHelper.commonForegroundColor);
//获得焦点时的insets
// putInsets("Slider.focusInsets", 2, 2, 7, 7); //父类中默认是 2, 2, 2, 2
//获得焦点时的焦点边框颜色
put("Slider.focus", BeautyEyeLNFHelper.commonFocusedBorderColor); //[r=113,g=111,b=100]
put("SliderUI", BESliderUI.class);
}
}

View File

@ -0,0 +1,140 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BESpinnerUI.java at 2015-2-1 20:25:39, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.spinner;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSpinnerUI;
import org.jackhuang.hmcl.laf.spinner.BESpinnerUI.GlyphButton.Type;
import org.jackhuang.hmcl.laf.BEUtils;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
/**
* JSPinner的UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
* @version 1.0
* @see com.sun.java.swing.plaf.windows.WindowsSpinnerUI
*/
public class BESpinnerUI extends BasicSpinnerUI {
private static final Icon9Factory ICON_9 = new Icon9Factory("spinner");
public static ComponentUI createUI(JComponent c) {
return new BESpinnerUI();
}
@Override
protected JComponent createEditor() {
JComponent e = super.createEditor();
e.setOpaque(false);
//参见JSpinner.NumberEditorsuper.createEditor()返回值就是它的父类
//是一个JPanel实例它是由一个FormatttedTextField及其父JPanel组成
//所以设置完 e.setOpaque(false)还要把它的子FormatttedTextField
//设置成透明其实它的子只有1个它里为了适用未来的扩展假设它有很多子
Component[] childs = e.getComponents();
BEUtils.componentsOpaque(childs, false);
return e;
}
/**
* Paint.
*
* @param g the g
* @param c the c {@inheritDoc}
*/
@Override
public void paint(Graphics g, JComponent c) {
if (spinner != null)
ICON_9.getWithEnabled("", spinner.isEnabled()).
draw((Graphics2D) g, 0, 0, c.getWidth(), c.getHeight());
super.paint(g, c);
}
@Override
protected Component createPreviousButton() {
JButton xpButton = new GlyphButton(spinner, Type.down);
Dimension size = UIManager.getDimension("Spinner.arrowButtonSize");
xpButton.setPreferredSize(size);
xpButton.setRequestFocusEnabled(false);
installPreviousButtonListeners(xpButton);
return xpButton;
}
@Override
protected Component createNextButton() {
JButton xpButton = new GlyphButton(spinner, Type.up);
Dimension size = UIManager.getDimension("Spinner.arrowButtonSize");
xpButton.setPreferredSize(size);
xpButton.setRequestFocusEnabled(false);
installNextButtonListeners(xpButton);
return xpButton;
}
/**
* @see com.sun.java.swing.plaf.windows.XPStyle.GlyphButton
*/
static class GlyphButton extends JButton {
private Type type = null;
/**
* The Enum Type.
*/
public enum Type {
down,
up
}
/**
* Instantiates a new glyph button.
*
* @param parent the parent
* @param type the type
*/
public GlyphButton(Component parent, Type type) {
// XPStyle xp = getXP();
// skin = xp.getSkin(parent, part);
this.type = type;
setBorder(null);
setContentAreaFilled(false);
setMinimumSize(new Dimension(5, 5));
setPreferredSize(new Dimension(16, 16));
setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
}
@Override
public boolean isFocusTraversable() {
return false;
}
@Override
public void paintComponent(Graphics g) {
ICON_9.get("button_" + type.name(), !isEnabled() || getModel().isPressed() ? "pressed" : "").
draw((Graphics2D) g, 0, 0, getWidth(), getHeight());
}
@Override
protected void paintBorder(Graphics g) {
}
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:37, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.spinner;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
public static void uiImpl() {
put("Spinner.background", BeautyEyeLNFHelper.commonBackgroundColor);
put("Spinner.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("SpinnerUI", BESpinnerUI.class);
//Spinner组件的边框
putBorder("Spinner.border", 5, 5, 10, 5); // 3, 3, 3, 3
//Spinner组件的2个箭头按钮的内衬距
putInsets("Spinner.arrowButtonInsets", 1, 0, 2, 2); // 1, 1, 1, 1
//Spinner组件的2个箭头按钮的默认大小
putDim("Spinner.arrowButtonSize", 17, 9);
}
}

View File

@ -0,0 +1,293 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BESplitPaneDivider.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.split;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import javax.swing.JButton;
import javax.swing.JSplitPane;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
import org.jackhuang.hmcl.laf.BEUtils;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
/**
* 分栏面板上的分隔线实现类.
* <p>
* TODO 两个Touch按钮的位置等都是可以定制的目前没有更好的美化灵感以后可以再深入优先
*
* @author Jack Jiang(jb2011@163.com), 2012-07-13
* @version 1.0
*/
public class BESplitPaneDivider extends BasicSplitPaneDivider {
private static final Icon9Factory ICON_9 = new Icon9Factory("split_touch");
private final int oneTouchSize;
/**
* TODO 本常量可以做成UIManager属性以便未来使用者进行配置哦.
*/
protected final Color TOUCH_BUTTON_COLOR = new Color(58, 135, 173);
/**
* 在水平SplitePane状态下中间触碰装饰区装饰按钮的宽度.
*/
protected final static int TOUCH_DECRATED_BUTTON_W = 5;//* TODO 本常量可以做成UIManager属性以便未来使用者进行配置哦
/**
* 在水平SplitePane状态下中间触碰装饰区装饰按钮的高度.
*/
protected final static int TOUCH_DECRATED_BUTTON_H = 30;//* TODO 本常量可以做成UIManager属性以便未来使用者进行配置哦
/**
* 分隔条线直线的颜色.
*/
protected final static Color TOUCH_DECRATED_BUTTON_COLOR = new Color(180, 180, 180);//* TODO 本颜色常量可以做成UIManager属性以便未来使用者进行配置哦
/**
* 分隔条线直线的高亮颜色用来形成高对比度的立体效果 .
*/
protected final static Color TOUCH_DECRATED_BUTTON_HILIGHT_COLOR = Color.white;//* TODO 本颜色常量可以做成UIManager属性以便未来使用者进行配置哦
public BESplitPaneDivider(BasicSplitPaneUI ui) {
super(ui);
oneTouchSize = UIManager.getInt("SplitPane.oneTouchButtonSize", ui.getSplitPane().getLocale());
}
@Override
public void paint(Graphics g) {
Color bgColor = (splitPane.hasFocus())
? UIManager.getColor("SplitPane.shadow") : getBackground();
Dimension size = getSize();
Graphics2D g2 = ((Graphics2D) g);
BEUtils.setAntiAliasing((Graphics2D) g, true);
// g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
// RenderingHints.VALUE_ANTIALIAS_ON);
if (bgColor != null) {
int orient = this.splitPane.getOrientation();
if (orient == JSplitPane.HORIZONTAL_SPLIT) {
int halfWidth = size.width / 2;
int halfHeight = size.height / 2;
//------------------------先水平居中画隔条竖线
//虚线样式
Stroke oldStroke = ((Graphics2D) g).getStroke();
Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0);//实线空白
((Graphics2D) g).setStroke(sroke);
g.setColor(TOUCH_DECRATED_BUTTON_COLOR);//bgColor);
// g.fillRect(0, 0, size.width, size.height);
g.drawLine(halfWidth + 0, 0, halfWidth + 0, size.height);
//在竖线右边再画一个高对比度的竖线从而形成立体效果
g.setColor(TOUCH_DECRATED_BUTTON_HILIGHT_COLOR);
g.drawLine(halfWidth + 1, 0, halfWidth + 1, size.height);
((Graphics2D) g).setStroke(oldStroke);
//------------------------再填充触碰装饰区
int decratedButton_w = TOUCH_DECRATED_BUTTON_W;
int decratedButton_h = TOUCH_DECRATED_BUTTON_H;//18;
int diverTouchStartX = halfWidth - decratedButton_w / 2;
ICON_9.get("bg1")
.draw((Graphics2D) g, diverTouchStartX, halfHeight - decratedButton_h / 2,
decratedButton_w, decratedButton_h);
} else {
int halfHeight = size.height / 2;
int halfWidth = size.width / 2;
//------------------------先垂直居中画分隔条横线
//虚线样式
Stroke oldStroke = ((Graphics2D) g).getStroke();
Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0);//实线空白
((Graphics2D) g).setStroke(sroke);
g.setColor(TOUCH_DECRATED_BUTTON_COLOR);//bgColor);
// g.fillRect(0, 0, size.width, size.height);
g.drawLine(0, halfHeight + 0, size.width, halfHeight + 0);
//在竖线下边再画一个高对比度的横线从而形成立体效果
g.setColor(TOUCH_DECRATED_BUTTON_HILIGHT_COLOR);
g.drawLine(0, halfHeight + 1, size.width, halfHeight + 1);
((Graphics2D) g).setStroke(oldStroke);
//------------------------再填充触碰装饰区
int decratedButton_w = TOUCH_DECRATED_BUTTON_W;
int decratedButton_h = TOUCH_DECRATED_BUTTON_H;//18;
int diverTouchStartY = halfHeight - decratedButton_w / 2;
ICON_9.get("bg1")
.draw((Graphics2D) g, halfWidth - decratedButton_h, diverTouchStartY,
decratedButton_h, decratedButton_w);
}
// g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
// RenderingHints.VALUE_ANTIALIAS_OFF);
BEUtils.setAntiAliasing((Graphics2D) g, false);
}
super.paint(g);
}
/**
* Creates and return an instance of JButton that can be used to collapse
* the left component in the split pane.
*
* 因父类方法继承重用设计不佳此处只能全部拷过来代码再行修改
* 至2012-07-13本方法只作了关于箭头按钮的填充颜色的改变
*
* @return the j button
* @see javax.swing.plaf.basic.BasicSplitPaneDivider#createLeftOneTouchButton()
*/
@Override
protected JButton createLeftOneTouchButton() {
JButton b = new JButton() {
@Override
public void setBorder(Border b) {
}
@Override
public void paint(Graphics g) {
if (splitPane != null) {
int[] xs = new int[3];
int[] ys = new int[3];
int blockSize;
// Fill the background first ...
g.setColor(this.getBackground());
g.fillRect(0, 0, this.getWidth(), this.getHeight());
// ... then draw the arrow.
g.setColor(TOUCH_BUTTON_COLOR);//Color.black);
//* 开启反走样
BEUtils.setAntiAliasing((Graphics2D) g, true);
if (orientation == JSplitPane.VERTICAL_SPLIT) {
blockSize = Math.min(getHeight(), oneTouchSize);
xs[0] = blockSize;
xs[1] = 0;
xs[2] = blockSize << 1;
ys[0] = 0;
ys[1] = ys[2] = blockSize;
g.drawPolygon(xs, ys, 3); // Little trick to make the
// arrows of equal size
} else {
blockSize = Math.min(getWidth(), oneTouchSize);
xs[0] = xs[2] = blockSize;
xs[1] = 0;
ys[0] = 0;
ys[1] = blockSize;
ys[2] = blockSize << 1;
}
g.fillPolygon(xs, ys, 3);
//* 关闭反走样
BEUtils.setAntiAliasing((Graphics2D) g, false);
}
}
// Don't want the button to participate in focus traversable.
@Override
public boolean isFocusTraversable() {
return false;
}
};
b.setMinimumSize(new Dimension(oneTouchSize, oneTouchSize));
b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
b.setFocusPainted(false);
b.setBorderPainted(false);
b.setRequestFocusEnabled(false);
return b;
}
/**
* Creates and return an instance of JButton that can be used to collapse
* the right component in the split pane.
*
* 因父类方法继承重用设计不佳此处只能全部拷过来代码再行修改
* 至2012-07-13本方法只作了关于箭头按钮的填充颜色的改变
*
* @return the j button
* @see javax.swing.plaf.basic.BasicSplitPaneDivider#createRightOneTouchButton()
*/
@Override
protected JButton createRightOneTouchButton() {
JButton b = new JButton() {
@Override
public void setBorder(Border border) {
}
@Override
public void paint(Graphics g) {
if (splitPane != null) {
int[] xs = new int[3];
int[] ys = new int[3];
int blockSize;
// Fill the background first ...
g.setColor(this.getBackground());
g.fillRect(0, 0, this.getWidth(),
this.getHeight());
//* 开启反走样
BEUtils.setAntiAliasing((Graphics2D) g, true);
// ... then draw the arrow.
if (orientation == JSplitPane.VERTICAL_SPLIT) {
blockSize = Math.min(getHeight(), oneTouchSize);
xs[0] = blockSize;
xs[1] = blockSize << 1;
xs[2] = 0;
ys[0] = blockSize;
ys[1] = ys[2] = 0;
} else {
blockSize = Math.min(getWidth(), oneTouchSize);
xs[0] = xs[2] = 0;
xs[1] = blockSize;
ys[0] = 0;
ys[1] = blockSize;
ys[2] = blockSize << 1;
}
g.setColor(TOUCH_BUTTON_COLOR);//Color.black);
g.fillPolygon(xs, ys, 3);
//* 关闭反走样
BEUtils.setAntiAliasing((Graphics2D) g, false);
}
}
// Don't want the button to participate in focus traversable.
@Override
public boolean isFocusTraversable() {
return false;
}
};
b.setMinimumSize(new Dimension(oneTouchSize, oneTouchSize));
b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
b.setFocusPainted(false);
b.setBorderPainted(false);
b.setRequestFocusEnabled(false);
return b;
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BESplitPaneUI.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.split;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
/**
* 分栏面板的UI实现.
*
* @author Jack Jiang(jb2011@163.com), 2012-07-10
* @version 1.0
*/
public class BESplitPaneUI extends BasicSplitPaneUI {
public BESplitPaneUI() {
super();
}
public static ComponentUI createUI(JComponent x) {
return new BESplitPaneUI();
}
@Override
public BasicSplitPaneDivider createDefaultDivider() {
return new BESplitPaneDivider(this);
}
}

View File

@ -0,0 +1,123 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* SplitPaneDividerBorder.java at 2015-2-1 20:25:41, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.split;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Insets;
import javax.swing.JSplitPane;
import javax.swing.border.Border;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
/**
* 分隔条的border实现类.
* <p>
* Draws the border around the divider in a splitpane. To get the appropriate
* effect, this needs to be used with a SplitPaneBorder.
*
* 主要修改了UI填充实现部分
*
* @author Jack Jiang(jb2011@163.com)
* @see javax.swing.plaf.basic.BasicBorders
*/
public class SplitPaneDividerBorder implements Border, UIResource {
// javax.swing.plaf.basic.BasicBorders.SplitPaneDividerBorder
// private Color highlight;
// private Color shadow;
// public SplitPaneDividerBorder(Color highlight, Color shadow)
// {
// this.highlight = highlight;
// this.shadow = shadow;
// }
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width,
int height) {
//在目前的视觉效果下不需要这个border的绘制哦
// Graphics2D g2d = (Graphics2D) g;
// Component child;
// Rectangle cBounds;
// JSplitPane splitPane = ((BasicSplitPaneDivider) c).getBasicSplitPaneUI().getSplitPane();
// Dimension size = c.getSize();
//
// child = splitPane.getLeftComponent();
// // This is needed for the space between the divider and end of
// // splitpane.
// g.setColor(c.getBackground());
// g.drawRect(x, y, width - 1, height - 1);
//
// if (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT)
// {
//// if (child != null)
//// {
//// g.setColor(shadow);//highlight);
//// g.drawLine(0, 0, 0, size.height);
//// }
//// child = splitPane.getRightComponent();
//// if (child != null)
//// {
//// g.setColor(shadow);
//// g.drawLine(size.width - 1, 0, size.width - 1, size.height);
//// }
// }
// else
// {
//// if (child != null)
//// {
//// g.setColor(shadow);//highlight);
//// g.drawLine(0, 0, size.width, 0);
//// }
//// child = splitPane.getRightComponent();
//// if (child != null)
//// {
//// g.setColor(shadow);
//// g.drawLine(0, size.height - 1, size.width,size.height - 1);
////
//// }
// }
}
@Override
public Insets getBorderInsets(Component c) {
Insets insets = new Insets(0, 0, 0, 0);
if (c instanceof BasicSplitPaneDivider) {
BasicSplitPaneUI bspui = ((BasicSplitPaneDivider) c)
.getBasicSplitPaneUI();
if (bspui != null) {
JSplitPane splitPane = bspui.getSplitPane();
if (splitPane != null) {
if (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
insets.top = insets.bottom = 0;
insets.left = insets.right = 1;
return insets;
}
// VERTICAL_SPLIT
insets.top = insets.bottom = 1;
insets.left = insets.right = 0;
return insets;
}
}
}
insets.top = insets.bottom = insets.left = insets.right = 1;
return insets;
}
@Override
public boolean isBorderOpaque() {
return true;
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:39, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.split;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
public static void uiImpl() {
putColor("SplitPane.shadow", 200, 200, 200); // 本属性在BE LNF中暂时没用到
//JSplitePane的默认背景色
putColor("SplitPane.background", 250, 250, 250); // 238, 241, 243
//JSplitePane的边框实现
put("SplitPane.border", new org.jackhuang.hmcl.laf.scroll.ScrollPaneBorder());// 0, 0, 0, 0
put("SplitPaneUI", BESplitPaneUI.class);
//分隔条拖动时的颜色说明此值可以设置alpha通道以便达到半透明效果哦
putColor("SplitPaneDivider.draggingColor", 0, 0, 0, 50);
//触碰按钮的默认大小
// see javax.swing.plaf.basic.BasicSplitPaneDivider.ONE_TOUCH_SIZE = 6
put("SplitPane.oneTouchButtonSize", 4);
//分隔条的默认大小
put("SplitPane.dividerSize", 7); //drfault is 5
//分隔条的边框实现
put("SplitPaneDivider.border", new SplitPaneDividerBorder());
}
}

View File

@ -0,0 +1,334 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BETabbedPaneUI.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.tab;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import org.jackhuang.hmcl.laf.BEUtils;
/**
* JTabbedPane的UI实现类.
*
* @author Jack Jiang(jb2011@163.com), 2012-01-12
* @version 1.1
* @see com.sun.java.swing.plaf.windows.WindowsTabbedPaneUI
*/
public class BETabbedPaneUI extends BasicTabbedPaneUI {
public static ComponentUI createUI(JComponent c) {
return new BETabbedPaneUI();
}
/**
* 本方法的重写copy自 com.sun.java.swing.plaf.windows.WindowsTabbedPaneUI基本未修改代码
* 重写父类方法实现rover状态下的tab的ui重绘父类方法只是实现了rolloverTab 的设置不步及ui重绘制因Basic
* LNF中没有实现rover状态的ui样式
*
* @see javax.swing.plaf.basic.BasicTabbedPaneUI#setRolloverTab(int)
*/
@Override
protected void setRolloverTab(int index) {
int oldRolloverTab = getRolloverTab();
super.setRolloverTab(index);
Rectangle r1 = null;
Rectangle r2 = null;
if ((oldRolloverTab >= 0) && (oldRolloverTab < tabPane.getTabCount()))
r1 = getTabBounds(tabPane, oldRolloverTab);
if (index >= 0)
r2 = getTabBounds(tabPane, index);
if (r1 != null)
if (r2 != null)
tabPane.repaint(r1.union(r2));
else
tabPane.repaint(r1);
else if (r2 != null)
tabPane.repaint(r2);
}
/**
* this function draws the border around each tab note that this function
* does now draw the background of the tab. that is done elsewhere.
*
* @param g the g
* @param tabPlacement the tab placement
* @param tabIndex the tab index
* @param x the x
* @param y the y
* @param w the w
* @param h the h
* @param isSelected the is selected
* @see javax.swing.plaf.basic.BasicTabbedPaneUI#paintTabBorder(java.awt.Graphics, int, int, int, int, int, int, boolean)
*/
@Override
protected void paintTabBorder(Graphics g, int tabPlacement,
int tabIndex, int x, int y, int w, int h, boolean isSelected) {
// g.setColor(lightHighlight);
// Graphics2D g2d = (Graphics2D)g;
Graphics2D g2d = (Graphics2D) g.create();
g2d.translate(x, y);
//* 由Jack Jiang添加true表示该tab当前正处于鼠标rover其上的状态
//* this.getRolloverTab()的返回值由父类方法 setRolloverTab()设定并实现ui重绘的
boolean isRover = (this.getRolloverTab() == tabIndex);
//* 由Jack Jiang添加true表示该tab处于可用状态否则表示处于禁用状态
boolean isEnableAt = this.tabPane.isEnabledAt(tabIndex);
switch (tabPlacement) {
case LEFT:
g2d.scale(-1.0, 1.0);
g2d.rotate(Math.toRadians(90.0));
paintTabBorderImpl(g2d, isEnableAt, isSelected, isRover, 0, 0, h, w);
break;
case RIGHT:
g2d.translate(w, 0);
g2d.rotate(Math.toRadians(90.0));
paintTabBorderImpl(g2d, isEnableAt, isSelected, isRover, 0, 0, h, w);
break;
case BOTTOM:
g2d.translate(0, h);
g2d.scale(-1.0, 1.0);
g2d.rotate(Math.toRadians(180.0));
paintTabBorderImpl(g2d, isEnableAt, isSelected, isRover, 0, 0, w, h);
break;
case TOP:
default:
paintTabBorderImpl(g2d, isEnableAt, isSelected, isRover, 0, 0, w, h);
break;
}
}
//* paintTabBorder的绘制实现方法2012-01-12日 BY Jack Jiang
/**
* Paint tab border impl.
*
* @param g2d the g2d
* @param isEnableAt the is enable at
* @param isSelected the is selected
* @param isRover the is rover
* @param x the x
* @param y the y
* @param w the w
* @param h the h
*/
private void paintTabBorderImpl(Graphics2D g2d, boolean isEnableAt, boolean isSelected,
boolean isRover, int x, int y, int w, int h) {
//** modified by jb2011 改为NinePatch图片实现Y + 1 的目的是使得选中时的底线能往下画一个像素这样好看点
if (isSelected) {
g2d.setColor(UIManager.getColor("TabbedPane.selectedForeground"));
g2d.fillRect(x, y + h - 1, w, 2);
}
//ICON_9.get("", isSelected ? "selected" : (isEnableAt && isRover ? "normal_rollover" : "normal"))
// .draw(g2d, x, y + 1, w, h);
}
/**
* 重写本方法的目的仅是把原来的默认实线变成虚线而已哦
*
* @see
* javax.swing.plaf.basic.BasicTabbedPaneUI#paintContentBorder(java.awt.Graphics,
* int, int)
*/
@Override
protected void paintContentBorder(Graphics g, int tabPlacement, int selectedIndex) {
/*//*** add by jb2011 2012-08-23 START
//虚线样式
Stroke oldStroke = ((Graphics2D) g).getStroke();
Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0);//实线空白
((Graphics2D) g).setStroke(sroke);
//*** add by jb2011 2012-08-23 END
*/
//调用父类默认实现
super.paintContentBorder(g, tabPlacement, selectedIndex);
/*
//*** add by jb2011 2012-08-23 START
((Graphics2D) g).setStroke(oldStroke);
//*** add by jb2011 2012-08-23 END*/
}
//
/**
* JTabbedPaneUI 内容面板的上边框绘制方法默认就是内容面板上方的那条灰色.
*
* @see
* javax.swing.plaf.basic.BasicTabbedPaneUI#paintContentBorderTopEdge(java.awt.Graphics,
* int, int, int, int, int, int)
*/
@Override
protected void paintContentBorderTopEdge(Graphics g, int tabPlacement,
int selectedIndex,
int x, int y, int w, int h) {
//此模式下不绘制其它3条边框视觉上好看一些
if (tabPlacement == TOP)
//调用父类默认实现
super.paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h);
}
/**
* JTabbedPaneUI 内容面板的左边框绘制方法.
*
* @see
* javax.swing.plaf.basic.BasicTabbedPaneUI#paintContentBorderLeftEdge(java.awt.Graphics,
* int, int, int, int, int, int)
*/
@Override
protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement,
int selectedIndex,
int x, int y, int w, int h) {
//此模式下不绘制其它3条边框视觉上好看一些
if (tabPlacement == LEFT)
//调用父类默认实现
super.paintContentBorderLeftEdge(g, tabPlacement, selectedIndex, x, y, w, h);
}
/**
* JTabbedPaneUI 内容面板的底边框绘制方法.
*
* @see
* javax.swing.plaf.basic.BasicTabbedPaneUI#paintContentBorderBottomEdge(java.awt.Graphics,
* int, int, int, int, int, int)
*/
@Override
protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement,
int selectedIndex,
int x, int y, int w, int h) {
//此模式下不绘制其它3条边框视觉上好看一些
if (tabPlacement == BOTTOM)
//调用父类默认实现
super.paintContentBorderBottomEdge(g, tabPlacement, selectedIndex, x, y, w, h);
}
/**
* JTabbedPaneUI 内容面板的右边框绘制方法.
*
* @see
* javax.swing.plaf.basic.BasicTabbedPaneUI#paintContentBorderRightEdge(java.awt.Graphics,
* int, int, int, int, int, int)
*/
@Override
protected void paintContentBorderRightEdge(Graphics g, int tabPlacement,
int selectedIndex,
int x, int y, int w, int h) {
//此模式下不绘制其它3条边框视觉上好看一些
if (tabPlacement == RIGHT)
//调用父类默认实现
super.paintContentBorderRightEdge(g, tabPlacement, selectedIndex, x, y, w, h);
}
/**
* 获得焦点时的虚线框绘制方法
*
* @see
* javax.swing.plaf.basic.BasicTabbedPaneUI#paintFocusIndicator(java.awt.Graphics,
* int, java.awt.Rectangle[], int, java.awt.Rectangle, java.awt.Rectangle,
* boolean)
*/
@Override
protected void paintFocusIndicator(Graphics g, int tabPlacement,
Rectangle[] rects, int tabIndex,
Rectangle iconRect, Rectangle textRect,
boolean isSelected) {
Rectangle tabRect = rects[tabIndex];
if (tabPane.hasFocus() && isSelected) {
int x, y, w, h;
g.setColor(focus);
switch (tabPlacement) {
case LEFT:
x = tabRect.x + 4;//父类中默认是+3
y = tabRect.y + 6;//父类中默认是+3
w = tabRect.width - 7;//父类中默认是 - 5
h = tabRect.height - 12;//父类中默认是-6
break;
case RIGHT:
x = tabRect.x + 4;//父类中默认是+ 2
y = tabRect.y + 6;//父类中默认是+ 3
w = tabRect.width - 9;//父类中默认是- 5
h = tabRect.height - 12;//父类中默认是- 6
break;
case BOTTOM:
x = tabRect.x + 6;//父类中默认是+ 3
y = tabRect.y + 4;//父类中默认是+ 2
w = tabRect.width - 12;//父类中默认是- 6
h = tabRect.height - 9;//父类中默认是- 5
break;
case TOP:
default:
//** modified by jb2011根据整体效果进行偏移修正
x = tabRect.x + 6;//父类中默认是+3
//** modified by jb2011根据整体效果进行偏移修正
y = tabRect.y + 4;//父类中默认是+3
//** modified by jb2011根据整体效果进行偏移修正
w = tabRect.width - 12;//父类中默认是-6
//** modified by jb2011-8的目的是使得焦点虚线框与选中底边保持一个像素的距离否则挨在一起在视觉上效果会较差
h = tabRect.height - 8;//父类中默认是 - 5
}
//** modified by jb2011绘制虚线方法改成可以设置虚线步进的方法步进设为2则更好看一点
// BasicGraphicsUtils.drawDashedRect(g, x, y, w, h);
BEUtils.drawDashedRect(g, x, y, w, h);
// 绘制虚线框的半透明白色立体阴影因主背景色较淡效果不明显但显然比没有要好
g.setColor(new Color(255, 255, 255, 255));// TODO 此值可提炼成UIManager属性哦
// 立体阴影就是向右下偏移一个像素实现的
BEUtils.drawDashedRect(g, x + 1, y + 1, w, h);
}
}
/**
* 重写并修改本方法的目的是修正tab上的文本显示Y坐标方向上的偏移以便与背景协调
* @see javax.swing.plaf.basic.BasicTabbedPaneUI#getTabLabelShiftY(int, int, boolean)
*/
@Override
protected int getTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected) {
return 0;
/*
switch (tabPlacement) {
case BOTTOM:
return isSelected ? 1 : -1;
case LEFT:
case RIGHT:
return rects[tabIndex].height % 2;
case TOP:
default:
//** 由jb2011 2012-08-24修改目的是使得选中时和未选中时的文本包括图标
//** 默认实现中之所以要产生它个效果是为了营造立体效果而BE LNF中并不需要
//** 不要往上或往下偏移的太多太多则相当难看
// nudge = isSelected? -1 : 1;//本行是原父类中的默认实现哦
return -2;//由jb2011修改目的是让文本相对现在的背景往上偏移一点好看一些
}*/
}
@Override
protected int getTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected) {
Rectangle tabRect = rects[tabIndex];
String propKey = "labelShift";
int nudge = UIManager.getInt("TabbedPane." + propKey);
switch (tabPlacement) {
case LEFT:
return nudge;
case RIGHT:
return -nudge;
case BOTTOM:
case TOP:
default:
return tabRect.width % 2;
}
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.tab;
import java.awt.Font;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
public static void uiImpl() {
FontUIResource f = (FontUIResource) UIManager.get("TabbedPane.font");
UIManager.put("TabbedPane.font", new FontUIResource(new Font(f.getName(), f.getStyle(), 14)));
put("TabbedPane.background", BeautyEyeLNFHelper.commonBackgroundColor);
put("TabbedPane.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("TabbedPane.opaque", false);
// put("TabbedPane.tabRunOverlay", 2);//本属性无效果
//false表示tab在边框虑线之上而不是重叠效果
put("TabbedPane.tabsOverlapBorder", true);
put("TabbedPaneUI", BETabbedPaneUI.class);
//此属性决定了整个JTabbedPane区域的内衬
putInsets("TabbedPane.tabAreaInsets", 3, 20, 2, 20);// 3, 2, 2, 2
//此属性决定了tab与内容面板间的空白
putInsets("TabbedPane.contentBorderInsets", 2, 0, 3, 0);// 2, 2, 3, 3
//此参数将决定选中时的tab与左右相邻tab的重合度正值表示重合负值表示间隔空白
//* 注意与NP图的边缘留白配合使用能达到更灵活的效果
putInsets("TabbedPane.selectedTabPadInsets", 0, 1, 0, 2);// 2, 2, 2, 1
//此属性决定了JTabbedPane的tab标签的内衬
putInsets("TabbedPane.tabInsets", 7, 7, 7, 7);
//获得焦点时的虚线框颜色
putColor("TabbedPane.focus", 130, 130, 130);
//在BE LNF中此颜色将决定TabPlacement=TOP和LEFT二种类型TabbedPane的内容面板那条虚线的颜色
putColor("TabbedPane.highlight", 228, 228, 231);//new Color(200,200,200)));
//在BE LNF中此颜色将决定TabPlacement=RIGHT和BOTTOM二种类型TabbedPane的内容面板那条虚线的颜色
put("TabbedPane.shadow", BeautyEyeLNFHelper.commonFocusedBorderColor);//192,192,192);
//在BE LNF中因TabPlacement=RIGHT和BOTTOM二种类型时父类方法会默认再多画一条深色立体线而使得在BE LNF中
//不好看此颜色设置的目的就是让此立体阴影线与背景色一致从而看不出它的效果进而不影响内容面板那条虚线在BE LNF中的视觉效果
put("TabbedPane.darkShadow", BeautyEyeLNFHelper.commonBackgroundColor);
}
}

View File

@ -0,0 +1,479 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BETableHeaderUI.java at 2015-2-1 20:25:38, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.table;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.Serializable;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTableHeaderUI;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
/**
* 表格头UI实现类
* <p>
* 本类代码只能用于JDK1.6及以上版本因JDK1.5及以下版本没法兼容本类中的很大一部分关键代码
*
* @author Jack Jiang(jb2011@163.com), 2011-03-28
* @see com.sun.java.swing.plaf.windows.WindowsTableHeaderUI
*/
public class BETableHeaderUI extends BasicTableHeaderUI {
protected static final Icon9Factory ICON_9 = new Icon9Factory("table");
private TableCellRenderer originalHeaderRenderer;
public static ComponentUI createUI(JComponent h) {
return new BETableHeaderUI();
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
originalHeaderRenderer = header.getDefaultRenderer();
if (originalHeaderRenderer instanceof UIResource)
header.setDefaultRenderer(new XPDefaultRenderer());
}
@Override
public void uninstallUI(JComponent c) {
if (header.getDefaultRenderer() instanceof XPDefaultRenderer)
header.setDefaultRenderer(originalHeaderRenderer);
super.uninstallUI(c);
}
@Override
protected void rolloverColumnUpdated(int oldColumn, int newColumn) {
header.repaint(header.getHeaderRect(oldColumn));
header.repaint(header.getHeaderRect(newColumn));
}
//绘制头Ui内容本方法提取出来是为了在ELineNumTable里也可以用到它是进行了自定义Ui头实现
/**
* Paint head cell.
*
* @param g the g
* @param headCellSize the head cell size
*/
public static void paintHeadCell(Graphics g, Dimension headCellSize) {
int w = headCellSize.width, h = headCellSize.height - 1;
// Graphics2D g2 = (Graphics2D)g;
// //渐变背景
// Paint oldp= g2.getPaint();
// GradientPaint gp = new GradientPaint(0, 0
// , new Color(250,250,250)
// , 0, h,new Color(241,241,241));
// g2.setPaint(gp);
// g.fillRect(0, 0, w, h);
// //矩形区下1/2处非渐变填充为了产生立体效果
// g2.setPaint(oldp);
//
// //上下线条突出立体感
// g.setColor(new Color(215,215,215));
// g.drawLine(0, 0, w, 0);
// g.setColor(new Color(249,250,249));
// g.drawLine(0, h-1, w, h-1);
// g.setColor(new Color(209,209,209));
// g.drawLine(0, h, w, h);
ICON_9.get("header_cell")
.draw((Graphics2D) g, 0, 0, w, h);//表头背景
ICON_9.get("header_cell_separator")
.draw((Graphics2D) g, w - 2, 0, 4, h - 1);//表头右边的分隔线,h-1是为了让分隔线往上移一个像素好看一点
}
public class DefaultTableCellHeaderRenderer extends DefaultTableCellRenderer
implements UIResource {
private boolean horizontalTextPositionSet;
private Icon sortArrow;
private final EmptyIcon emptyIcon = new EmptyIcon();
public DefaultTableCellHeaderRenderer() {
setHorizontalAlignment(JLabel.CENTER);
}
@Override
public void setHorizontalTextPosition(int textPosition) {
horizontalTextPositionSet = true;
super.setHorizontalTextPosition(textPosition);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Icon sortIcon = null;
boolean isPaintingForPrint = false;
if (table != null) {
JTableHeader header = table.getTableHeader();
if (header != null) {
Color fgColor = null;
Color bgColor = null;
if (hasFocus) {
fgColor = UIManager.getColor("TableHeader.focusCellForeground", this.getLocale());
bgColor = UIManager.getColor("TableHeader.focusCellBackground", this.getLocale());
}
if (fgColor == null)
fgColor = header.getForeground();
if (bgColor == null)
bgColor = header.getBackground();
setForeground(fgColor);
setBackground(bgColor);
setFont(header.getFont());
isPaintingForPrint = header.isPaintingForPrint();
}
if (!isPaintingForPrint && table.getRowSorter() != null) {
if (!horizontalTextPositionSet)
// There is a row sorter, and the developer hasn't
// set a text position, change to leading.
setHorizontalTextPosition(JLabel.LEADING);
SortOrder sortOrder = getColumnSortOrder(table, column);
if (sortOrder != null)
switch (sortOrder) {
case ASCENDING:
sortIcon = UIManager.getIcon("Table.ascendingSortIcon", this.getLocale());
break;
case DESCENDING:
sortIcon = UIManager.getIcon("Table.descendingSortIcon", this.getLocale());
break;
case UNSORTED:
sortIcon = UIManager.getIcon("Table.naturalSortIcon", this.getLocale());
break;
}
}
}
setText(value == null ? "" : value.toString());
setIcon(sortIcon);
sortArrow = sortIcon;
Border border = null;
if (hasFocus)
border = UIManager.getBorder("TableHeader.focusCellBorder", this.getLocale());
if (border == null)
border = UIManager.getBorder("TableHeader.cellBorder", this.getLocale());
setBorder(border);
return this;
}
public SortOrder getColumnSortOrder(JTable table, int column) {
SortOrder rv = null;
if (table == null || table.getRowSorter() == null)
return rv;
java.util.List<? extends RowSorter.SortKey> sortKeys
= table.getRowSorter().getSortKeys();
if (sortKeys.size() > 0 && sortKeys.get(0).getColumn()
== table.convertColumnIndexToModel(column))
rv = sortKeys.get(0).getSortOrder();
return rv;
}
@Override
public void paintComponent(Graphics g) {
boolean b = UIManager.getBoolean("TableHeader.rightAlignSortArrow", this.getLocale());
if (b && sortArrow != null) {
//emptyIcon is used so that if the text in the header is right
//aligned, or if the column is too narrow, then the text will
//be sized appropriately to make room for the icon that is about
//to be painted manually here.
emptyIcon.width = sortArrow.getIconWidth();
emptyIcon.height = sortArrow.getIconHeight();
setIcon(emptyIcon);
super.paintComponent(g);
Point position = computeIconPosition(g);
sortArrow.paintIcon(this, g, position.x, position.y);
} else
super.paintComponent(g);
}
private Point computeIconPosition(Graphics g) {
FontMetrics fontMetrics = g.getFontMetrics();
Rectangle viewR = new Rectangle();
Rectangle textR = new Rectangle();
Rectangle iconR = new Rectangle();
Insets i = getInsets();
viewR.x = i.left;
viewR.y = i.top;
viewR.width = getWidth() - (i.left + i.right);
viewR.height = getHeight() - (i.top + i.bottom);
SwingUtilities.layoutCompoundLabel(
this,
fontMetrics,
getText(),
sortArrow,
getVerticalAlignment(),
getHorizontalAlignment(),
getVerticalTextPosition(),
getHorizontalTextPosition(),
viewR,
iconR,
textR,
getIconTextGap());
int x = getWidth() - i.right - sortArrow.getIconWidth();
int y = iconR.y;
return new Point(x, y);
}
private class EmptyIcon implements Icon, Serializable {
int width = 0;
int height = 0;
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
}
@Override
public int getIconWidth() {
return width;
}
@Override
public int getIconHeight() {
return height;
}
}
}
private class XPDefaultRenderer extends DefaultTableCellHeaderRenderer {
XPDefaultRenderer() {
setHorizontalAlignment(LEADING);
setVerticalAlignment(CENTER);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
//** 本方法里可以有默认设置render字体和颜色的设置所以即使在上面构造方法里设置自已的字体等都不起效
//在此方法调用之后调置是没有问题的
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
// this.isSelected = isSelected;
// this.hasFocus = hasFocus;
// this.column = column;
// this.hasRollover = (column == getRolloverColumn());
// if (skin == null)
// {
// skin = BEXPStyle.getXP().getSkin(header, Part.HP_HEADERITEM);
// }
Insets margins = UIManager.getInsets("TableHeader.cellMargin");//skin.getContentMargin();
Border border;
int contentTop = 0;
int contentLeft = 0;
int contentBottom = 0;
int contentRight = 0;
if (margins != null) {
contentTop = margins.top;
contentLeft = margins.left;
contentBottom = margins.bottom;
contentRight = margins.right;
}
/* idk:
* Both on Vista and XP there is some offset to the
* HP_HEADERITEM content. It does not seem to come from
* Prop.CONTENTMARGINS. Do not know where it is defined.
* using some hardcoded values.
*/
contentLeft += 5;
contentBottom += 4;
contentRight += 5;
/* On Vista sortIcon is painted above the header's text.
* We use border to paint it.
*/
Icon sortIcon;
//原UI代码
// if (ZCWindowsLookAndFeel.isOnVista()&&
// ((sortIcon = getIcon()) instanceof javax.swing.plaf.UIResource
// || sortIcon == null))
//现代码上面原Java源代码里有WindowsLookAndFeel.isOnVista()==true时才会进入下面的代码
//逻辑是不对的也就是只要不是vista就不可能绘制排序图标这估计是Jdk自带的Java源代码很可能不是最新的
if ( //去掉vista判断
// ZCWindowsLookAndFeel.isOnVista()
// &&
((sortIcon = getIcon()) instanceof javax.swing.plaf.UIResource || sortIcon == null)) {
//原UI代码原代码里为了仿vista样式标头高度很高现注释掉
// contentTop += 1;
setIcon(null);
sortIcon = null;
SortOrder sortOrder = getColumnSortOrder(table, column);
if (sortOrder != null)
switch (sortOrder) {
case ASCENDING:
sortIcon
= UIManager.getIcon("Table.ascendingSortIcon");
break;
case DESCENDING:
sortIcon
= UIManager.getIcon("Table.descendingSortIcon");
break;
}
if (sortIcon != null)
//原UI代码原代码里为了仿vista样式标头高度很高现注释掉
// contentBottom = sortIcon.getIconHeight();
border = new IconBorder(sortIcon, contentTop, contentLeft,
contentBottom, contentRight);
else {
sortIcon = UIManager.getIcon("Table.ascendingSortIcon");
int sortIconHeight = (sortIcon != null) ? sortIcon.getIconHeight() : 0;
if (sortIconHeight != 0) {
//原UI代码原代码里为了仿vista样式标头高度很高现注释掉
// contentBottom = sortIconHeight;
}
border = new EmptyBorder(
//原UI代码原代码里为了仿vista样式标头高度很高现注释掉
// sortIconHeight + contentTop, contentLeft, contentBottom, contentRight);
// /现代码border的top不要那么原代码是为了仿vista的
contentTop, contentLeft, contentBottom, contentRight);
}
} else {
contentTop += 3;
border = new EmptyBorder(contentTop, contentLeft, contentBottom, contentRight);
}
setBorder(border);
//** jb2011设置字体颜色和加粗
// this.setForeground(ColorHelper.DARK_GRAY1_LIKE_APPLE);
// this.setFont(this.getFont().deriveFont(Font.BOLD));
return this;
}
@Override
public void paint(Graphics g) {
Dimension size = getSize();
// State state = State.NORMAL;
// TableColumn draggedColumn = header.getDraggedColumn();
// if (draggedColumn != null &&
// column == SwingUtilities2.convertColumnIndexToView(
// header.getColumnModel(),
// draggedColumn.getModelIndex()))
// {
// state = State.PRESSED;
// }
// else if (isSelected || hasFocus || hasRollover)
// {
// state = State.HOT;
// }
/* on Vista there are more states for sorted columns */
// if (WinUtils.isOnVista())
// {
// SortOrder sortOrder = getColumnSortOrder(header.getTable(), column);
// if (sortOrder != null)
// {
// switch(sortOrder)
// {
// case ASCENDING:
// /* falls through */
// case DESCENDING:
// switch (state)
// {
// case NORMAL:
// state = State.SORTEDNORMAL;
// break;
// case PRESSED:
// state = State.SORTEDPRESSED;
// break;
// case HOT:
// state = State.SORTEDHOT;
// break;
// default:
// /* do nothing */
// }
// default :
// /* do nothing */
// }
// }
// }
paintHeadCell(g, size);
// skin.paintSkin(g, 0, 0, size.width-1, size.height-1, state);
super.paint(g);
}
}
//* 由jb2011 修改自WindowsTableHeaderUI里的同名类.
/**
* A border with an Icon at the middle of the top side. Outer insets can be
* provided for this border.
*/
private static class IconBorder implements Border, UIResource {
private final Icon icon;
private final int top, left, bottom, right;
public IconBorder(Icon icon, int top, int left, int bottom, int right) {
this.icon = icon;
this.top = top;
this.left = left;
this.bottom = bottom;
this.right = right;
}
@Override
public Insets getBorderInsets(Component c) {
//原UI代码原代码里为了仿vista样式标头高度很高现注释掉
// return new Insets(icon.getIconHeight() + top, left, bottom, right);
//现代码
return new Insets(top, left, bottom, right);
}
@Override
public boolean isBorderOpaque() {
return false;
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
icon.paintIcon(c, g,
//原UI代码原代码里为了仿vista样式标头高度很高且图标的位置是放在top中央现注释掉
// x + left + (width - left - right - icon.getIconWidth()) / 2, y + top);
//现代码图标放在右边利往左来2个像素的位置好看一点
x + left + width - right - icon.getIconWidth() - 2, y);
}
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BETableUI.java at 2015-2-1 20:25:41, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.table;
import java.awt.Dimension;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.UIDefaults;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTableUI;
/**
* JTable的UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
*/
public class BETableUI extends BasicTableUI {
UIDefaults defaultRenderersByColumnClass;
public static ComponentUI createUI(JComponent c) {
return new BETableUI();
}
/**
* Initialize JTable properties, e.g. font, foreground, and background. The
* font, foreground, and background properties are only set if their current
* value is either null or a UIResource, other properties are set if the
* current value is null.
*
* @see #installUI
*/
@Override
protected void installDefaults() {
super.installDefaults();
//行高设置为25看起来会舒服些
table.setRowHeight(25);
//不显示垂直的网格线
table.setShowVerticalLines(false);
//设置单元格间的空白默认是1个像素宽和高
//说明设置本参数可以实现单元格间的间隔空制间隔里通常是实现网格线的绘制
//网格维绘制与否并不影响间隔的存在如果间隔存在但网格线不绘的话它就是是透明的空
//参数中width表示水平间隔height表示垂直间隔为0则表示没有间隔
table.setIntercellSpacing(new Dimension(0, 1));
LookAndFeel.installProperty(table, "opaque", Boolean.FALSE);
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* FocusCellHighlightBorder.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.table;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Insets;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import org.jackhuang.hmcl.laf.BEUtils;
/**
* 表格单元获得焦点时的Border实现类.
*
* 本border由Jack Jiang实现它是表格单元获得焦点时的边框类似的功能在windows LNF下是一个距形虚线框
*
* @author Jack Jiang(jb2011@163.com)
*/
class FocusCellHighlightBorder extends AbstractBorder {
@Override
public Insets getBorderInsets(Component c) {
// return new Insets(0,3,0,1);
return new Insets(2, 2, 2, 2); // @since 3.5
}
@Override
public Insets getBorderInsets(Component c, Insets insets) {
return getBorderInsets(c);
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
//* old impl
// //在左边划一条2像素宽的竖线
// g.setColor(UIManager.getColor("Table.focusCellHighlightBorderColor"));
// g.fillRect(x, y, 2, height );//上下各空白一个像素目的是为了与render的N9图片背景配合形成更好的视觉效果
//
// //再在上面的竖线右边划一条1像素宽的亮色竖线以便为上面的2像素竖线营造立体效果
// /* ~~注这个属性是jb2011为了更好的ui效果自已加的属性目的是使Table.focusCellHighlightBorder有点立体效果哦 */
// g.setColor(UIManager.getColor("Table.focusCellHighlightBorderHighlightColor"));
// g.fillRect(x+2, y, 1, height );
//* @since 3.5
BEUtils.draw4RecCorner(g, x, y, width - 2, height - 2, 5,
UIManager.getColor("Table.focusCellHighlightBorderColor"));
BEUtils.draw4RecCorner(g, x + 1, y + 1, width - 2, height - 2, 5,
UIManager.getColor("Table.focusCellHighlightBorderHighlightColor"));
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* TableScrollBorder.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.table;
import java.awt.Insets;
import org.jackhuang.hmcl.laf.widget.border.NinePatchBorder;
/**
* 表格UI所在滚动条的边框实现类.
*
* @author Jack Jiang(jb2011@163.com), 2012-08-30
* @version 1.0
*/
class TableScrollBorder extends NinePatchBorder {
public TableScrollBorder() {
super(new Insets(3, 5, 10, 5), BETableHeaderUI.ICON_9.get("scroll_border"));
}
}

View File

@ -0,0 +1,102 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:39, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.table;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import javax.swing.UIManager;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.IconFactory;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
private static final IconFactory ICON = new IconFactory("table");
public static void uiImpl() {
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JTable的相关ui属性设定
//JTable所属的滚动面板的border实现不像JListJTable的UI自动为它配备的一个JScrollPane
put("Table.scrollPaneBorder", new TableScrollBorder());//defaut is com.sun.java.swing.plaf.windows.XPStyle.XPFillBorder
put("Table.focusCellHighlightBorder", new FocusCellHighlightBorder());//new BEDashedBorder(new Color(0,160,0),1,0,true,false,true,false)));
/* ~~注这个属性是jb2011为了更好的ui效果自已加的属性 */
put("Table.focusCellHighlightBorderColor", Color.white);//new ColorUIResource(Color.red));
/* ~~注这个属性是jb2011为了更好的ui效果自已加的属性目的是使Table.focusCellHighlightBorder有点立体效果哦 */
putColor("Table.focusCellHighlightBorderHighlightColor", 255, 255, 255, 70);//注意这个颜色是半透明的哦
put("Table.background", Color.white);
//** 2011-03-16 add by jb2011 为了使JDK1.6及以上表格头在排序时能显示排序箭头1.6里的排序图标是在UI里设定的
UIManager.put("Table.descendingSortIcon", ICON.get("descending_sort"));
UIManager.put("Table.ascendingSortIcon", ICON.get("ascending_sort"));
put("Table.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor);
putColor("Table.gridColor", 220, 220, 220);
put("Table.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
put("Table.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("TableUI", BETableUI.class);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JTable表头相关ui属性设定
// UIManager.put("TableHeader.font",new Font("宋体",Font.PLAIN,12));//此属性将决定表头的字体
put("TableHeader.background", BeautyEyeLNFHelper.commonBackgroundColor);
put("TableHeader.foreground", BeautyEyeLNFHelper.commonForegroundColor);
//不建议完全定制表头ui因为BasicTableHeaderUI里的关键方法都是private无法继承重写要实现自已
//的绘制逻辑需要重写大段代码而因JTable在不同jdk版本里的变动较大比如1.6里才有的排序及图标及相关方法
//在不同的版本里都不尽相同而且调用了若干sun的非公开包里的api虽存在兼容性问题为了UI美观还是自定义实现吧
put("TableHeaderUI", BETableHeaderUI.class);
//** BE LNF的本属性只在Java版本高于1.5时起效
//* 由jb2011自已加的属性因原BasicTableHeaderUI里用TableHeader.cellBorder来设置
//border但WindowsTableHeaderUI的border则是自已实现的IconBorder而BE LNF中则是仿
//照Windows LNF实现所以只能实现一个自已的属性来供以后的使用者灵活设定否则只能像Windows LNF一样硬编码在代码里
putInsets("TableHeader.cellMargin", 7, 0, 7, 0);
}
/**
* Border for a Table Header.
*
* @see javax.swing.plaf.metal.TableHeaderBorder
*/
public static class TableHeaderBorder extends javax.swing.border.AbstractBorder {
protected Insets editorBorderInsets = new Insets(7, 0, 7, 0);//默认是2, 2, 2, 0 );
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
g.translate(x, y);
// g.setColor(MetalLookAndFeel.getControlDarkShadow() );
// g.drawLine( w-1, 0, w-1, h-1 );
// g.drawLine( 1, h-1, w-1, h-1 );
// g.setColor( MetalLookAndFeel.getControlHighlight() );
// g.drawLine( 0, 0, w-2, 0 );
// g.drawLine( 0, 0, 0, h-2 );
//* add by Jack Jiang START
//绘制表头单元的底部水平线跟网格线颜色一样就可以了
g.setColor(UIManager.getColor("Table.gridColor"));
g.drawLine(0, h - 1, w, h - 1);
//绘制表头单元的右分隔竖线
BETableHeaderUI.ICON_9.get("header_cell_separator")
.draw((Graphics2D) g, w - 4, 0, 4, h);
//* add by Jack Jiang END
g.translate(-x, -y);
}
@Override
public Insets getBorderInsets(Component c) {
return editorBorderInsets;
}
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEEditorPaneUI.java at 2015-2-1 20:25:41, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.textcoms;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicEditorPaneUI;
import javax.swing.text.JTextComponent;
import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable;
import org.jb2011.ninepatch4j.NinePatch;
/**
* 文本组件JEditorPane的UI实现类.
*
* @author Jack Jiang(jb2011@163.com), 2012-08-25
* @see com.sun.java.swing.plaf.windows.WindowsEditorPaneUI
*/
public class BEEditorPaneUI extends BasicEditorPaneUI implements BgSwitchable,
org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported {
//默认是纯白色背景因为JEditorPane肯定是要放在JScrollPane中的而ScrollPane也是有边框的
//如果JEditorPane再有边框就很难看了所以JEditorPane在没有获得焦点时就已无边框效果出现会好看很多
private NinePatch bg = __UI__.ICON_9.get("white");
public static ComponentUI createUI(JComponent c) {
BETextFieldUI.addOtherListener(c);
// c.addMouseListener(new NLLookAndFeel.EditMenu());
return new BEEditorPaneUI();
}
//* 本方法由Jack Jiang于2012-09-07日加入
/**
* 是否使用父类的绘制实现方法true表示是.
* <p>
* 因为在BE LNF中边框和背景等都是使用N9图没法通过设置背景色和前景
* 色来控制JEditorPane的颜色和边框本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE
* LNF中默认的N9图填充绘制而改用父类中的方法父类中的方法 就可以支持颜色的设置罗只是丑点但总归是能适应用户的需求场景要求其实用户完全可以
* 通过JEditorPane.setUI(..)方式来自定义UI哦.
*
* @return true, if is use parent paint
*/
@Override
public boolean isUseParentPaint() {
return getComponent() != null
&& (!(getComponent().getBorder() instanceof UIResource)
|| !(getComponent().getBackground() instanceof UIResource));
}
/**
* Paints a background for the view. This will only be called if isOpaque()
* on the associated component is true. The default is to paint the
* background color of the component.
*
* @param g the graphics context
*/
@Override
protected void paintBackground(Graphics g) {
//先调用父类方法把背景刷新下比如本UI里使用的大圆角NP图如不先刷新背景则会因上下拉动滚动条
//而致4个圆角位置得不到刷新从而影响视觉效果边角有前面的遗留置于透明边角不被透明像素填
//充的问题它有可能是Android的NinePatch技术为了性能做作出的优化一切全透明像素即意味着不需绘制
super.paintBackground(g); // TODO 出于节约计算资源考生虑本行代码换成父类中默认填充背景的代码即可
//* 如果用户作了自定义颜色设置则使用父类方法来实现绘制否则BE LNF中没法支持这些设置哦
if (!isUseParentPaint()) {
//用新的NP图实现真正的背景填充
JTextComponent editor = this.getComponent();
BETextFieldUI.paintBg(g, 0, 0, editor.getWidth(), editor.getHeight(),
editor.isEnabled(), border);
}
}
@Override
public void switchBgToNormal() {
border = __UI__.BORDER_NORMAL;
}
@Override
public void switchBgToFocused() {
border = __UI__.border_focused();
}
@Override
public void switchBgToOver() {
border = __UI__.BORDER_OVER;
}
Color border = __UI__.BORDER_NORMAL;
// /**
// * Creates the object to use for a caret. By default an
// * instance of WindowsCaret is created. This method
// * can be redefined to provide something else that implements
// * the InputPosition interface or a subclass of DefaultCaret.
// *
// * @return the caret object
// */
// protected Caret createCaret() {
// return new WindowsTextUI.WindowsCaret();
// }
}

View File

@ -0,0 +1,100 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEPasswordFieldUI.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.textcoms;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicFormattedTextFieldUI;
import javax.swing.text.JTextComponent;
import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable;
import org.jb2011.ninepatch4j.NinePatch;
/**
* 文本组件JFormattedTextField的UI实现类.
*
* @author Jack Jiang(jb2011@163.com), 2015-11-13
* @since 3.7
*/
public class BEFormattedTextFieldUI extends BasicFormattedTextFieldUI implements BgSwitchable,
org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported {
private NinePatch bg = __UI__.ICON_9.get("normal");
public static ComponentUI createUI(JComponent c) {
c.addFocusListener(FocusListenerImpl.getInstance());
return new BEFormattedTextFieldUI();
}
//* 本方法由Jack Jiang于2012-09-07日加入
/**
* 是否使用父类的绘制实现方法true表示是.
* <p>
* 因为在BE LNF中边框和背景等都是使用N9图没法通过设置背景色和前景
* 色来控制JPasswordField的颜色和边框本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE
* LNF中默认的N9图填充绘制而改用父类中的方法父类中的方法 就可以支持颜色的设置罗只是丑点但总归是能适应用户的需求场景要求其实用户完全可以
* 通过JPasswordField.setUI(..)方式来自定义UI哦.
*
* @return true, if is use parent paint
*/
@Override
public boolean isUseParentPaint() {
return getComponent() != null
&& (!(getComponent().getBorder() instanceof UIResource)
|| !(getComponent().getBackground() instanceof UIResource));
}
/**
* Paints a background for the view. This will only be called if isOpaque()
* on the associated component is true. The default is to paint the
* background color of the component.
*
* @param g the graphics context
*/
@Override
protected void paintBackground(Graphics g) {
//先调用父类方法把背景刷新下比如本UI里使用的大圆角NP图如不先刷新背景则会因上下拉动滚动条
//而致4个圆角位置得不到刷新从而影响视觉效果边角有前面的遗留置于透明边角不被透明像素填
//充的问题它有可能是Android的NinePatch技术为了性能做作出的优化一切全透明像素即意味着不需绘制
super.paintBackground(g);// TODO 出于节约计算资源考生虑本行代码换成父类中默认填充背景的代码即可
//* 如果用户作了自定义颜色设置则使用父类方法来实现绘制否则BE LNF中没法支持这些设置哦
if (!isUseParentPaint()) {
//用新的NP图实现真正的背景填充
JTextComponent editor = this.getComponent();
BETextFieldUI.paintBg(g, 0, 0, editor.getWidth(), editor.getHeight(),
editor.isEnabled(), border);
}
}
@Override
public void switchBgToNormal() {
border = __UI__.BORDER_NORMAL;
}
@Override
public void switchBgToFocused() {
border = __UI__.border_focused();
}
@Override
public void switchBgToOver() {
border = __UI__.BORDER_OVER;
}
Color border = __UI__.BORDER_NORMAL;
}

View File

@ -0,0 +1,99 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEPasswordFieldUI.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.textcoms;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicPasswordFieldUI;
import javax.swing.text.JTextComponent;
import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable;
import org.jb2011.ninepatch4j.NinePatch;
/**
* 文本组件JPasswordField的UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
*/
public class BEPasswordFieldUI extends BasicPasswordFieldUI implements BgSwitchable,
org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported {
private NinePatch bg = __UI__.ICON_9.get("normal");
public static ComponentUI createUI(JComponent c) {
c.addFocusListener(FocusListenerImpl.getInstance());
// c.addMouseListener(new NLLookAndFeel.EditMenu());
return new BEPasswordFieldUI();
}
//* 本方法由Jack Jiang于2012-09-07日加入
/**
* 是否使用父类的绘制实现方法true表示是.
* <p>
* 因为在BE LNF中边框和背景等都是使用N9图没法通过设置背景色和前景
* 色来控制JPasswordField的颜色和边框本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE
* LNF中默认的N9图填充绘制而改用父类中的方法父类中的方法 就可以支持颜色的设置罗只是丑点但总归是能适应用户的需求场景要求其实用户完全可以
* 通过JPasswordField.setUI(..)方式来自定义UI哦.
*
* @return true, if is use parent paint
*/
@Override
public boolean isUseParentPaint() {
return getComponent() != null
&& (!(getComponent().getBorder() instanceof UIResource)
|| !(getComponent().getBackground() instanceof UIResource));
}
/**
* Paints a background for the view. This will only be called if isOpaque()
* on the associated component is true. The default is to paint the
* background color of the component.
*
* @param g the graphics context
*/
@Override
protected void paintBackground(Graphics g) {
//先调用父类方法把背景刷新下比如本UI里使用的大圆角NP图如不先刷新背景则会因上下拉动滚动条
//而致4个圆角位置得不到刷新从而影响视觉效果边角有前面的遗留置于透明边角不被透明像素填
//充的问题它有可能是Android的NinePatch技术为了性能做作出的优化一切全透明像素即意味着不需绘制
super.paintBackground(g);// TODO 出于节约计算资源考生虑本行代码换成父类中默认填充背景的代码即可
//* 如果用户作了自定义颜色设置则使用父类方法来实现绘制否则BE LNF中没法支持这些设置哦
if (!isUseParentPaint()) {
//用新的NP图实现真正的背景填充
JTextComponent editor = this.getComponent();
BETextFieldUI.paintBg(g, 0, 0, editor.getWidth(), editor.getHeight(),
editor.isEnabled(), border);
}
}
@Override
public void switchBgToNormal() {
border = __UI__.BORDER_NORMAL;
}
@Override
public void switchBgToFocused() {
border = __UI__.border_focused();
}
@Override
public void switchBgToOver() {
border = __UI__.BORDER_OVER;
}
Color border = __UI__.BORDER_NORMAL;
}

View File

@ -0,0 +1,102 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BETextAreaUI.java at 2015-2-1 20:25:41, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.textcoms;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTextAreaUI;
import javax.swing.text.JTextComponent;
import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable;
import org.jb2011.ninepatch4j.NinePatch;
/**
* 文本组件JTextArea的UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
*/
public class BETextAreaUI extends BasicTextAreaUI implements BgSwitchable,
org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported//WindowsTextAreaUI
{
//默认是纯白色背景因为JTextArea肯定是要放在JScrollPane中的而ScrollPane也是有边框的
//如果JTextArea再有边框就很难看了所以JTextArea在没有获得焦点时就已无边框效果出现会好看很多
private NinePatch bg = __UI__.ICON_9.get("white");
public static ComponentUI createUI(JComponent c) {
BETextFieldUI.addOtherListener(c);
// c.addMouseListener(new NLLookAndFeel.EditMenu());
return new BETextAreaUI();
}
//* 本方法由Jack Jiang于2012-09-07日加入
/**
* 是否使用父类的绘制实现方法true表示是.
* <p>
* 因为在BE LNF中边框和背景等都是使用N9图没法通过设置背景色和前景
* 色来控制JTextField的颜色和边框本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE
* LNF中默认的N9图填充绘制而改用父类中的方法父类中的方法 就可以支持颜色的设置罗只是丑点但总归是能适应用户的需求场景要求其实用户完全可以
* 通过JTextField.setUI(..)方式来自定义UI哦.
*
* @return true, if is use parent paint
*/
@Override
public boolean isUseParentPaint() {
return getComponent() != null
&& (!(getComponent().getBorder() instanceof UIResource)
|| !(getComponent().getBackground() instanceof UIResource));
}
/**
* Paints a background for the view. This will only be called if isOpaque()
* on the associated component is true. The default is to paint the
* background color of the component.
*
* @param g the graphics context
*/
@Override
protected void paintBackground(Graphics g) {
//先调用父类方法把背景刷新下比如本UI里使用的大圆角NP图如不先刷新背景则会因上下拉动滚动条
//而致4个圆角位置得不到刷新从而影响视觉效果边角有前面的遗留置于透明边角不被透明像素填
//充的问题它有可能是Android的NinePatch技术为了性能做作出的优化一切全透明像素即意味着不需绘制
super.paintBackground(g);// TODO 出于节约计算资源考生虑本行代码换成父类中默认填充背景的代码即可
//* 如果用户作了自定义颜色设置则使用父类方法来实现绘制否则BE LNF中没法支持这些设置哦
if (!isUseParentPaint()) {
//用新的NP图实现真正的背景填充
JTextComponent editor = this.getComponent();
BETextFieldUI.paintBg(g, 0, 0, editor.getWidth(), editor.getHeight(),
editor.isEnabled(), border);
}
}
@Override
public void switchBgToNormal() {
border = __UI__.BORDER_NORMAL;
}
@Override
public void switchBgToFocused() {
border = __UI__.border_focused();
}
@Override
public void switchBgToOver() {
border = __UI__.BORDER_OVER;
}
Color border = __UI__.BORDER_NORMAL;
}

View File

@ -0,0 +1,205 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BETextFieldUI.java at 2015-2-1 20:25:37, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.textcoms;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTextFieldUI;
import javax.swing.text.JTextComponent;
import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable;
import org.jb2011.ninepatch4j.NinePatch;
/**
* 文本组件JTextField的UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
*/
public class BETextFieldUI extends BasicTextFieldUI implements BgSwitchable,
org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported {
private NinePatch bg = __UI__.ICON_9.get("normal");
public static BETextFieldUI createUI(JComponent c) {
addOtherListener(c);
return new BETextFieldUI();
}
//* 本方法由Jack Jiang于2012-09-07日加入
/**
* 是否使用父类的绘制实现方法true表示是.
* <p>
* 因为在BE LNF中边框和背景等都是使用N9图没法通过设置背景色和前景
* 色来控制JTextField的颜色和边框本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE
* LNF中默认的N9图填充绘制而改用父类中的方法父类中的方法 就可以支持颜色的设置罗只是丑点但总归是能适应用户的需求场景要求其实用户完全可以
* 通过JTextField.setUI(..)方式来自定义UI哦.
*
* @return true, if is use parent paint
*/
@Override
public boolean isUseParentPaint() {
return getComponent() != null
&& (!(getComponent().getBorder() instanceof UIResource)
|| !(getComponent().getBackground() instanceof UIResource));
}
/**
* Paints a background for the view. This will only be called if isOpaque()
* on the associated component is true. The default is to paint the
* background color of the component.
*
* @param g the graphics context
*/
@Override
protected void paintBackground(Graphics g) {
// Color bgc = editor.getBackground();
// g.setColor(bgc);
// //先填 充背景
// g.fillRect(0, 0, editor.getWidth(), editor.getHeight());
//
// //(1) ---- 仿Numbus文本框效果
// //** top立体效果实现
// //(0,0)开始的第一条线会被后来的border覆盖掉的所以此处绘制没有意义不搞了
//// g.setColor(new Color(0,0,0));
//// g.drawLine(0, 0, editor.getWidth(), 0);
// //第2条线颜色淡一点
// g.setColor(new Color(208,208,208));
// g.drawLine(0, 1, editor.getWidth(), 1);
// //第3条线颜色更淡一点
// g.setColor(new Color(231,231,225));
// g.drawLine(0, 2, editor.getWidth(), 2);
//先调用父类方法把背景刷新下比如本UI里使用的大圆角NP图如不先刷新背景则会因上下拉动滚动条
//而致4个圆角位置得不到刷新从而影响视觉效果边角有前面的遗留置于透明边角不被透明像素填
//充的问题它有可能是Android的NinePatch技术为了性能做作出的优化一切全透明像素即意味着不需绘制
super.paintBackground(g);// TODO 出于节约计算资源考生虑本行代码换成父类中默认填充背景的代码即可
//* 如果用户作了自定义颜色设置则使用父类方法来实现绘制否则BE LNF中没法支持这些设置哦
if (!isUseParentPaint()) {
//用新的NP图实现真正的背景填充
JTextComponent editor = this.getComponent();
BETextFieldUI.paintBg(g, 0, 0, editor.getWidth(), editor.getHeight(),
editor.isEnabled(), border);
}
// if(this.getComponent().isEnabled())
// //*** 重要说明因使用的NinePatch图片作填充背景所以后绪任何对JTextField设置
// //*** 背景色将不会起效因为背景是用图片填充而非传统方法绘制出来的
// bg.draw((Graphics2D)g, 0, 0, editor.getWidth(), editor.getHeight());
// else
// __Icon9Factory__.getInstance().getTextFieldBgDisabled()
// .draw((Graphics2D)g, 0, 0, editor.getWidth(), editor.getHeight());
//// //(2) ---- 仿360软件管家文本框效果不太好看
// //** top立体效果实现
// //(0,0)开始的第一条线会被后来的border覆盖掉的所以此处绘制没有意义不搞了
//// g.setColor(new Color(0,0,0));
//// g.drawLine(0, 0, editor.getWidth(), 0);
// //第2条线颜色淡一点
// g.setColor(new Color(232,232,232));
// g.drawLine(1, 1, editor.getWidth()-1, 1);
// //第3条线颜色更淡一点
// g.setColor(new Color(241,241,241));
// g.drawLine(1, 2, editor.getWidth()-1, 2);
// //第4条线颜色更淡一点
// g.setColor(new Color(248,248,248));
// g.drawLine(1, 3, editor.getWidth()-1, 3);
// //第5条线颜色更淡一点
// g.setColor(new Color(252,252,252));
// g.drawLine(1, 4, editor.getWidth()-1, 4);
//
// //** left
// //第2条线颜色淡一点
// g.setColor(new Color(241,241,241));
// g.drawLine(1, 1, 1, editor.getHeight()-1);
// //第3条线颜色淡一点
// g.setColor(new Color(248,248,248));
// g.drawLine(2, 1, 2, editor.getHeight()-1);
// //第4条线颜色淡一点
// g.setColor(new Color(253,253,253));
// g.drawLine(3, 1, 3, editor.getHeight()-1);
//
// //** right
// //第2条线颜色淡一点
// g.setColor(new Color(241,241,241));
// g.drawLine(editor.getWidth()-1, 1, editor.getWidth()-1, editor.getHeight()-1);
// //第3条线颜色淡一点
// g.setColor(new Color(248,248,248));
// g.drawLine(editor.getWidth()-2, 1, editor.getWidth()-2, editor.getHeight()-1);
// //第4条线颜色淡一点
// g.setColor(new Color(253,253,253));
// g.drawLine(editor.getWidth()-3, 1, editor.getWidth()-3, editor.getHeight()-1);
//
// //** bottom
// //第2条线颜色淡一点
// g.setColor(new Color(248,248,248));
// g.drawLine(1, editor.getHeight()-1, editor.getWidth()-1, editor.getHeight()-1);
// //第3条线颜色淡一点
// g.setColor(new Color(252,252,252));
// g.drawLine(1, editor.getHeight()-2, editor.getWidth()-1, editor.getHeight()-2);
}
@Override
public void switchBgToNormal() {
border = __UI__.BORDER_NORMAL;
}
@Override
public void switchBgToFocused() {
border = __UI__.border_focused();
}
@Override
public void switchBgToOver() {
border = __UI__.BORDER_OVER;
}
Color border = __UI__.BORDER_NORMAL;
/**
* Paint bg.
*
* @param g the g
* @param x the x
* @param y the y
* @param w the w
* @param h the h
* @param enabled the enabled
* @param bg the bg
*/
public static void paintBg(Graphics g, int x, int y, int w, int h,
boolean enabled, Color border) {
if (enabled) {
g.setColor(border);
g.fillRect(x, y, w, h);
g.setColor(Color.white);
g.fillRect(x + 2, y + 2, w - 4, h - 4);
}
else
__UI__.ICON_9.get("disabled")
.draw((Graphics2D) g, x, y, w, h);
}
/**
* 为组件添加焦点监听器获得/取消焦点时可以自动设置/取消一个彩色的边框效果以体高UI体验 右键菜单监听器有复制/粘贴等功能.
*
* @param c the c
*/
public static void addOtherListener(JComponent c) {
c.addFocusListener(FocusListenerImpl.getInstance());
c.addMouseListener(FocusListenerImpl.getInstance());
}
}

View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BETextPaneUI.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.textcoms;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTextPaneUI;
import javax.swing.text.JTextComponent;
import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable;
import org.jb2011.ninepatch4j.NinePatch;
/**
* 文本组件JTextPane的UI实现类.
*
* @author Jack Jiang(jb2011@163.com), 2012-08-25
* @see com.sun.java.swing.plaf.windows.WindowsTextPaneUI
*/
public class BETextPaneUI extends BasicTextPaneUI implements BgSwitchable,
org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported {
//默认是纯白色背景因为JTextPane肯定是要放在JScrollPane中的而ScrollPane也是有边框的
//如果JTextPane再有边框就很难看了所以JTextPane在没有获得焦点时就已无边框效果出现会好看很多
private NinePatch bg = __UI__.ICON_9.get("white");
public static ComponentUI createUI(JComponent c) {
BETextFieldUI.addOtherListener(c);
// c.addMouseListener(new NLLookAndFeel.EditMenu());
return new BETextPaneUI();
}
/**
* 是否使用父类的绘制实现方法true表示是.
* <p>
* 因为在BE LNF中边框和背景等都是使用N9图没法通过设置背景色和前景
* 色来控制JTextPane的颜色和边框本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE
* LNF中默认的N9图填充绘制而改用父类中的方法父类中的方法 就可以支持颜色的设置罗只是丑点但总归是能适应用户的需求场景要求其实用户完全可以
* 通过JTextPane.setUI(..)方式来自定义UI哦.
*
* @return true, if is use parent paint
*/
@Override
public boolean isUseParentPaint() {
return getComponent() != null
&& (!(getComponent().getBorder() instanceof UIResource)
|| !(getComponent().getBackground() instanceof UIResource));
}
/**
* Paints a background for the view. This will only be called if isOpaque()
* on the associated component is true. The default is to paint the
* background color of the component.
*
* @param g the graphics context
*/
@Override
protected void paintBackground(Graphics g) {
//先调用父类方法把背景刷新下比如本UI里使用的大圆角NP图如不先刷新背景则会因上下拉动滚动条
//而致4个圆角位置得不到刷新从而影响视觉效果边角有前面的遗留置于透明边角不被透明像素填
//充的问题它有可能是Android的NinePatch技术为了性能做作出的优化一切全透明像素即意味着不需绘制
super.paintBackground(g);// TODO 出于节约计算资源考生虑本行代码换成父类中默认填充背景的代码即可
//* 如果用户作了自定义颜色设置则使用父类方法来实现绘制否则BE LNF中没法支持这些设置哦
if (!isUseParentPaint()) {
//用新的NP图实现真正的背景填充
JTextComponent editor = this.getComponent();
BETextFieldUI.paintBg(g, 0, 0, editor.getWidth(), editor.getHeight(),
editor.isEnabled(), border);
}
}
@Override
public void switchBgToNormal() {
border = __UI__.BORDER_NORMAL;
}
@Override
public void switchBgToFocused() {
border = __UI__.border_focused();
}
@Override
public void switchBgToOver() {
border = __UI__.BORDER_OVER;
}
Color border = __UI__.BORDER_NORMAL;
// /**
// * Creates the object to use for a caret. By default an
// * instance of WindowsCaret is created. This method
// * can be redefined to provide something else that implements
// * the InputPosition interface or a subclass of DefaultCaret.
// *
// * @return the caret object
// */
// protected Caret createCaret() {
// return new WindowsTextUI.WindowsCaret();
// }
}

View File

@ -0,0 +1,249 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* FocusListenerImpl.java at 2015-2-1 20:25:40, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.textcoms;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;
import javax.swing.text.JTextComponent;
import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable;
import org.jackhuang.hmcl.laf.BEUtils;
import org.jackhuang.hmcl.laf.widget.border.BERoundBorder;
/**
* 焦点改变时的监听器实现类.
* <p>
* 目前主要用于各文本组件.
*
* @author Jack Jiang(jb2011@163.com)
*/
public class FocusListenerImpl implements FocusListener, MouseListener {
/**
* 文本组件等获得焦点后的边框线条宽度.
*/
public static int defaultFocusedThikness = 2;
/**
* Gets the single instance of FocusListenerImpl.
*
* @return single instance of FocusListenerImpl
*/
public static FocusListenerImpl getInstance() {
// return INSTANCE;
return new FocusListenerImpl();
}
/**
* The focused thikness.
*/
protected int focusedThikness = defaultFocusedThikness;
/**
* Gets the focused thikness.
*
* @return the focused thikness
*/
public int getFocusedThikness() {
return focusedThikness;
}
/**
* Sets the focused thikness.
*
* @param focusedThikness the focused thikness
* @return the focus listener impl
*/
public FocusListenerImpl setFocusedThikness(int focusedThikness) {
this.focusedThikness = focusedThikness;
return this;
}
@Override
public void focusGained(FocusEvent e) {
if (e.getSource() instanceof JComponent) {
JComponent com = (JComponent) e.getSource();
Border orignalBorder = com.getBorder();
if (orignalBorder != null) {
//决定获得焦点时的连框色调
Color focusedColor = getTextFieldFocusedColor();
//JTextField获得焦点时特殊处理自动切换它的背景图即可用NinePatch图实现
if (com instanceof JTextComponent) {
JTextComponent text = (JTextComponent) com;
ComponentUI ui = text.getUI();
text.putClientProperty("BEFocused", true);
if (ui instanceof BgSwitchable) {
((BgSwitchable) ui).switchBgToFocused();
com.repaint();
return;
}
} else if (com instanceof JComboBox)
focusedColor = getComboBoxFocusedColor();
//获得焦点后的新边框
BERoundBorder cc;
if (orignalBorder instanceof BERoundBorder)
cc = (BERoundBorder) (((BERoundBorder) orignalBorder).clone());
else
cc = new BERoundBorder(1).setArcWidth(0);
cc.setLineColor(focusedColor);
cc.setThickness(focusedThikness);
//* 当组件是JPasswordField,它的反应会有bug,也就是在setBorder之后它的
//* preferredSize会变的很小这里针对其作的特殊处理就是为了使其size与setBorder前保持一致
Dimension oldDm = null;
if (com instanceof JTextField)
oldDm = com.getSize();
com.setBorder(cc);
if (com instanceof JTextField)
com.setPreferredSize(oldDm);
}
}
}
@Override
public void focusLost(FocusEvent e) {
if (e.getSource() instanceof JComponent) {
JComponent com = (JComponent) e.getSource();
//JTextField获得焦点时特殊处理自动切换它的背景图即可用NinePatch图实现
if (com instanceof JTextComponent) {
JTextComponent text = (JTextComponent) com;
ComponentUI ui = text.getUI();
text.putClientProperty("BEFocused", false);
if (ui instanceof BgSwitchable) {
((BgSwitchable) ui).switchBgToNormal();
com.repaint();
return;
}
}
//失去焦点时还原边框样式
Border orignalBorder = com.getBorder();
if (orignalBorder != null)
if (orignalBorder instanceof BERoundBorder) {
BERoundBorder cc = (BERoundBorder) (((BERoundBorder) orignalBorder).clone());
cc.setLineColor(BERoundBorder.defaultLineColor);
cc.setThickness(1);
com.setBorder(cc);
}
}
}
/**
* Gets the text field focused color.
*
* @return the text field focused color
*/
public static Color getTextFieldFocusedColor() {
return BEUtils.getColor(UIManager.getColor("TextField.selectionBackground"), 30, 30, 30);
}
/**
* Gets the combo box focused color.
*
* @return the combo box focused color
*/
public static Color getComboBoxFocusedColor() {
return BEUtils.getColor(UIManager.getColor("ComboBox.selectionBackground"), 30, 30, 30);
}
// public static Color getTextPaneFocusedColor()
// {
// return LNFUtils.getColor(UIManager.getColor("TextPane.selectionBackground"),30,30,30);
// }
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
if (e.getSource() instanceof JComponent) {
JComponent com = (JComponent) e.getSource();
//JTextField获得焦点时特殊处理自动切换它的背景图即可用NinePatch图实现
if (com instanceof JTextComponent) {
JTextComponent text = (JTextComponent) com;
ComponentUI ui = text.getUI();
Object o = text.getClientProperty("BEFocused");
if (o == null || o == Boolean.FALSE)
if (ui instanceof BgSwitchable) {
((BgSwitchable) ui).switchBgToOver();
com.repaint();
return;
}
}
//失去焦点时还原边框样式
Border orignalBorder = com.getBorder();
if (orignalBorder != null)
if (orignalBorder instanceof BERoundBorder) {
BERoundBorder cc = (BERoundBorder) (((BERoundBorder) orignalBorder).clone());
cc.setLineColor(BERoundBorder.defaultLineColor);
cc.setThickness(1);
com.setBorder(cc);
}
}
}
@Override
public void mouseExited(MouseEvent e) {
if (e.getSource() instanceof JComponent) {
JComponent com = (JComponent) e.getSource();
//JTextField获得焦点时特殊处理自动切换它的背景图即可用NinePatch图实现
if (com instanceof JTextComponent) {
JTextComponent text = (JTextComponent) com;
ComponentUI ui = text.getUI();
Object o = text.getClientProperty("BEFocused");
if (o == null || o == Boolean.FALSE)
if (ui instanceof BgSwitchable) {
((BgSwitchable) ui).switchBgToNormal();
com.repaint();
return;
}
}
//失去焦点时还原边框样式
Border orignalBorder = com.getBorder();
if (orignalBorder != null)
if (orignalBorder instanceof BERoundBorder) {
BERoundBorder cc = (BERoundBorder) (((BERoundBorder) orignalBorder).clone());
cc.setLineColor(BERoundBorder.defaultLineColor);
cc.setThickness(1);
com.setBorder(cc);
}
}
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:38, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.textcoms;
import java.awt.Color;
import javax.swing.UIManager;
import javax.swing.plaf.InsetsUIResource;
import org.jackhuang.hmcl.util.ui.GraphicsUtils;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
import org.jackhuang.hmcl.laf.utils.UI;
import org.jackhuang.hmcl.laf.widget.border.BERoundBorder;
public class __UI__ extends UI {
static final Color BORDER_NORMAL = GraphicsUtils.getWebColor("#999999");
static final Color BORDER_OVER = GraphicsUtils.getWebColor("#666666");
static Color border_focused() {
return (Color) UIManager.get("TextField.focused");
}
public static final Icon9Factory ICON_9 = new Icon9Factory("text");
public static void uiImpl() {
final InsetsUIResource iuir = new InsetsUIResource(4, 7, 4, 7);
final BERoundBorder berb = new BERoundBorder().setLineColor(new Color(0, 0, 0, 0));
//使用全透明色绘边框用什么边框无所谓关键是读取它的margin并透明目的就是要让它的背景显现出来NinePatch图实现
UIManager.put("TextField.margin", iuir);
put("TextField.border", berb);
put("TextField.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor);
put("TextField.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
put("TextField.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("TextFieldUI", BETextFieldUI.class);
UIManager.put("FormattedTextField.margin", iuir);
put("FormattedTextField.border", new BERoundBorder(1).setArcWidth(10).setLineColor(new Color(0, 0, 0, 0)));
put("FormattedTextField.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("FormattedTextField.inactiveBackground", BeautyEyeLNFHelper.commonBackgroundColor);
put("FormattedTextField.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor);
put("FormattedTextField.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
put("FormattedTextFieldUI", BEFormattedTextFieldUI.class);
UIManager.put("PasswordField.margin", iuir);
put("PasswordField.border", berb);
put("PasswordField.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor);
put("PasswordField.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
put("PasswordField.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("PasswordFieldUI", BEPasswordFieldUI.class);
UIManager.put("TextArea.margin", iuir);
put("TextArea.border", berb);
put("TextArea.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor);
put("TextArea.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
put("TextArea.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("TextAreaUI", BETextAreaUI.class);
put("TextPane.border", berb);
put("TextPane.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor);
put("TextPane.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
put("TextPane.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("TextPaneUI", BETextPaneUI.class);
put("EditorPane.border", berb);
put("EditorPane.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor);
put("EditorPane.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor);
put("EditorPane.foreground", BeautyEyeLNFHelper.commonForegroundColor);
put("EditorPaneUI", BEEditorPaneUI.class);
}
public interface BgSwitchable {
void switchBgToNormal();
void switchBgToFocused();
void switchBgToOver();
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* __UI__.java at 2015-2-1 20:25:39, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.titlepane;
import javax.swing.UIManager;
import javax.swing.plaf.BorderUIResource;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.laf.BEUtils;
import org.jackhuang.hmcl.laf.utils.IconFactory;
import org.jackhuang.hmcl.laf.utils.UI;
public class __UI__ extends UI {
protected static final IconFactory ICON = new IconFactory("frame");
public static void uiImpl() {
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 窗体ui的各项属性设定
//*~ 本属性是Jack Jiang自已设定的Java的Metal主题默认对非Frame对象的窗口图标取的是InternalFrame.icon这是不对的
UIManager.put("Frame.icon", ICON.get("icon"));
UIManager.put("Frame.iconifyIcon", ICON.get("iconify"));
UIManager.put("Frame.iconifyIcon_rover", ICON.get("iconify_over"));
UIManager.put("Frame.iconifyIcon_pressed", ICON.get("iconify_pressed"));
UIManager.put("Frame.minimizeIcon", ICON.get("min"));
UIManager.put("Frame.minimizeIcon_rover", ICON.get("min_over"));
UIManager.put("Frame.minimizeIcon_pressed", ICON.get("min_pressed"));
UIManager.put("Frame.maximizeIcon", ICON.get("max"));
UIManager.put("Frame.maximizeIcon_rover", ICON.get("max_over"));
UIManager.put("Frame.maximizeIcon_pressed", ICON.get("max_pressed"));
UIManager.put("Frame.closeIcon", ICON.get("close"));
UIManager.put("Frame.closeIcon_rover", ICON.get("close_over"));
UIManager.put("Frame.closeIcon_pressed", ICON.get("close_pressed"));
//设定用于演示之用的设置按钮图标
UIManager.put("Frame.setupIcon", ICON.get("setup"));
// put("activeCaption", Windows2LookAndFeel.activeCaption);
put("activeCaptionText", BeautyEyeLNFHelper.activeCaptionTextColor);
// put("activeCaptionBorder", Windows2LookAndFeel.activeCaptionBorder);
// put("inactiveCaption", GraphicHandler.getColor(activeCaption, 64, 42, 22));
put("inactiveCaptionText", BEUtils.getColor(BeautyEyeLNFHelper.activeCaptionTextColor, -49, -27, -7));
// put("inactiveCaptionBorder", GraphicHandler.getColor(activeCaptionBorder, 64, 42, 22));
//此属性即是BeautyEye LNF的窗口标题栏实现
put("RootPaneUI", BERootPaneUI.class);
// These bindings are only enabled when there is a default
// button set on the rootpane.
UIManager.put("RootPane.defaultButtonWindowKeyBindings", new Object[] {
"ENTER", "press",
"released ENTER", "release",
"ctrl ENTER", "press",
"ctrl released ENTER", "release"
});
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> OptionPane的各项ui属性设定
Object dialogBorder = new BorderUIResource(BeautyEyeLNFHelper.getFrameBorder());//BorderFactory.createLineBorder(new Color(181,181,181)));
UIManager.put("RootPane.frameBorder", dialogBorder);
UIManager.put("RootPane.plainDialogBorder", dialogBorder);
UIManager.put("RootPane.informationDialogBorder", dialogBorder);
UIManager.put("RootPane.errorDialogBorder", dialogBorder);
UIManager.put("RootPane.colorChooserDialogBorder", dialogBorder);
UIManager.put("RootPane.fileChooserDialogBorder", dialogBorder);
UIManager.put("RootPane.questionDialogBorder", dialogBorder);
UIManager.put("RootPane.warningDialogBorder", dialogBorder);
}
}

View File

@ -0,0 +1,115 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEToolBarSeparatorUI.java at 2015-2-1 20:25:36, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.toolbar;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import javax.swing.JComponent;
import javax.swing.JSeparator;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicToolBarSeparatorUI;
/**
* JToolBar的分隔条UI实现类.
*
* @author Jack Jiang(jb2011@163.com)
* @see com.sun.java.swing.plaf.windows.WindowsToolBarSeparatorUI
*/
public class BEToolBarSeparatorUI extends BasicToolBarSeparatorUI {
public static ComponentUI createUI(JComponent c) {
return new BEToolBarSeparatorUI();
}
@Override
public Dimension getPreferredSize(JComponent c) {
Dimension size = ((JToolBar.Separator) c).getSeparatorSize();
if (size != null)
size = size.getSize();
else {
size = new Dimension(6, 6);
if (((JSeparator) c).getOrientation() == SwingConstants.VERTICAL)
size.height = 0;
else
size.width = 0;
}
return size;
}
@Override
public Dimension getMaximumSize(JComponent c) {
Dimension pref = getPreferredSize(c);
if (((JSeparator) c).getOrientation() == SwingConstants.VERTICAL)
return new Dimension(pref.width, Short.MAX_VALUE);
else
return new Dimension(Short.MAX_VALUE, pref.height);
}
@Override
public void paint(Graphics g, JComponent c) {
boolean vertical = ((JSeparator) c).getOrientation() == SwingConstants.VERTICAL;
Dimension size = c.getSize();
//虚线样式
Stroke oldStroke = ((Graphics2D) g).getStroke();
Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0);//实线空白
((Graphics2D) g).setStroke(sroke);//
Color temp = g.getColor();
UIDefaults table = UIManager.getLookAndFeelDefaults();
Color shadow = table.getColor("ToolBar.shadow");
Color highlight = table.getColor("ToolBar.highlight");
// TODO BUG_001不知何故垂直分隔条并不能像水平分隔条一样拥有默认设置的new Dimension(6, 6)
// 而只有new Dimension(1, ...)而当它floating时却能正常表现(只能绘出hilight而不能绘出shadow)
//有待深入研究垂直的分隔条则不会有此种情况
if (vertical) {
int x = (size.width / 2) - 1;
//* 当BUG_001存在时暂时使用以下代码解决把本该显示hilight的
//* 线条用shadow颜色绘制最大可能保证ui的正常展现
// g.setColor(shadow);
// g.drawLine(x, 2, x, size.height - 2);
g.setColor(shadow);//highlight);
g.drawLine(x + 1, 2, x + 1, size.height - 2);
//* 当BUG_001不存在时应该使用以下代码
// g.setColor(shadow);
// g.drawLine(x, 2, x, size.height - 2);
// g.setColor(highlight);
// g.drawLine(x + 1, 2, x + 1, size.height - 2);
} else {
int y = (size.height / 2) - 1;
g.setColor(shadow);
g.drawLine(2, y, size.width - 2, y);
g.setColor(highlight);
g.drawLine(2, y + 1, size.width - 2, y + 1);
}
g.setColor(temp);
((Graphics2D) g).setStroke(oldStroke);
}
}

View File

@ -0,0 +1,362 @@
/*
* Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
* All rights reserved.
* Project URL:https://github.com/JackJiang2011/beautyeye
* Version 3.6
*
* Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* BEToolBarUI.java at 2015-2-1 20:25:41, original version by Jack Jiang.
* You can contact author with jb2011@163.com.
*/
package org.jackhuang.hmcl.laf.toolbar;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Stroke;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicToolBarUI;
import org.jackhuang.hmcl.laf.button.BEButtonUI;
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
import org.jb2011.ninepatch4j.NinePatch;
/**
* JToolBar的UI实现类
*
* <p>
* <b>Since v3.4</b><br>
* 可以使用"ToolBar.isPaintPlainBackground"来控制BEToolBarUI还是
* 默认的渐变NinePatch图实现背景的填充效果好但是背景比较强烈不适于组件密集的场景.
* 全局控制可以通过UIManager.put("ToolBar.isPaintPlainBackground",
* Boolean.FALSE)UIManager中默认是false
* 或者通过JToolBar.putClientProperty("ToolBar.isPaintPlainBackground",
* Boolean.FALSE) 独立控制ClientProperty中的设置拥有最高优先级
*
* 特别说明JToolBar比较特殊加入到JToolBar中的组件其UI主要是Border将由ToolBarUI额
* 外控制而不受自身UI控制比如放入到JToolBar中的JToggleButton它的border就是受ToolBarUI
* 控制这些JToggleButton将无论如何修改ToolgleButtonUI.border也不会起效
*
* @author Jack Jiang(jb2011@163.com)
* @see com.sun.java.swing.plaf.windows.WindowsToolBarUI
*/
public class BEToolBarUI extends BasicToolBarUI
implements org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported {
private static final Icon9Factory ICON_9 = new Icon9Factory("toolbar");
public static ComponentUI createUI(JComponent c) {
return new BEToolBarUI();
}
@Override
protected void installDefaults() {
setRolloverBorders(true);
super.installDefaults();
}
//* 本方法由Jack Jiang于2012-09-07日加入
/**
* 是否使用父类的绘制实现方法true表示是.
* <p>
* 因为在BE LNF中工具条背景是使用N9图没法通过设置背景色和前景
* 色来控制工具条的颜色本方法的目的就是当用户设置了工具条的Background 时告之本实现类不使用BE
* LNF中默认的N9图填充绘制而改用父类中的方法父类中的方法 就可以支持颜色的设置罗只是丑点但总归是能适应用户的需求场景要求其实用户完全可以
* 通过JToolBar.setUI(new MetalToolBar())等方式来自定义UI哦.
*
* @return true, if is use parent paint
*/
@Override
public boolean isUseParentPaint() {
return toolBar != null
&& (!(toolBar.getBackground() instanceof UIResource));
}
@Override
protected Border createRolloverBorder() {
return new EmptyBorder(3, 3, 3, 3);
}
@Override
protected Border createNonRolloverBorder() {
return new EmptyBorder(3, 3, 3, 3);
}
@Override
public void paint(Graphics g, JComponent c) {
//~* @since 3.4, add by Jack Jiang 2012-11-05
//~* BeautyEye外观的特有定制属性true表示BEToolBarUI里将使用其它典型外观
//~* 一样的默认纯色填充背景颜色由ToolBar.background属性指定, 否则将使用BeautyEye
//~* 默认的渐变NinePatch图实现背景的填充另外还可以使用
//~* JToolBar.putClientProperty("ToolBar.isPaintPlainBackground", Boolean.TRUE);来进行
//~* 独立控制背景的填充方法ClientProperty相比UIManager中的本方法拥有最高优先级
boolean isPaintPlainBackground = false;
String isPaintPlainBackgroundKey = "ToolBar.isPaintPlainBackground";//~* BeautyEye外观的特有定制属性@since 3.4
//首先看看有没有独立在ClientProperty中设置"ToolBar.isPaintPlainBackground"属性ClientProperty中设置拥有最高优先级
Object isPaintPlainBackgroundObj = c.getClientProperty(isPaintPlainBackgroundKey);
//如果ClientProperty中没有设置则尝试取UIManager中的该属性默认值
if (isPaintPlainBackgroundObj == null)
isPaintPlainBackgroundObj = UIManager.getBoolean(isPaintPlainBackgroundKey);
if (isPaintPlainBackgroundObj != null)
isPaintPlainBackground = (Boolean) isPaintPlainBackgroundObj;
//* 如果用户作了自定义颜色设置则使用父类方法来实现绘制否则BE LNF中没法支持这些设置哦
if (isPaintPlainBackground || isUseParentPaint())
super.paint(g, c);
else {
//* 根据工具条所放在父类的位置不同来决定它的背景该使用哪个图片图片的差别在于方向不同主要是边缘阴影的方向
NinePatch np = ICON_9.get("north");
//int orientation = toolBar.getOrientation();
Container parent = toolBar.getParent();
if (parent != null) {
LayoutManager lm = parent.getLayout();
if (lm instanceof BorderLayout) {
Object cons = ((BorderLayout) lm).getConstraints(toolBar);
if (cons != null)
if (cons.equals(BorderLayout.NORTH))
np = ICON_9.get("north");
else if (cons.equals(BorderLayout.SOUTH))
np = ICON_9.get("south");
else if (cons.equals(BorderLayout.WEST))
np = ICON_9.get("west");
else if (cons.equals(BorderLayout.EAST))
np = ICON_9.get("east");
}
}
np.draw((Graphics2D) g, 0, 0, c.getWidth(), c.getHeight());
}
}
/**
* Gets the rollover border.
*
* @param b the b
* @return the rollover border {@inheritDoc}
*/
@Override
protected Border getRolloverBorder(AbstractButton b) {
return new BEButtonUI.BEEmptyBorder(new Insets(3, 3, 3, 3));
}
//* 由jb2011修改只加了一行代码哦
/**
* 重写父类方法实现自已的容器监听器. 自定义的目的就是为了把加入到其中的组件设置为透明因为BE LNF的工具栏是有背景否则
* 因有子组件的背景存在而使得整体很难看.
*
* @return the container listener
*/
@Override
protected ContainerListener createToolBarContListener() {
return new ToolBarContListenerJb2011();
}
//* 由jb2011修改自父类的Handler里的ContainerListener监听代码
/**
* The Class ToolBarContListenerJb2011.
*/
protected class ToolBarContListenerJb2011 implements ContainerListener {
//
// ContainerListener
//
@Override
public void componentAdded(ContainerEvent evt) {
Component c = evt.getChild();
if (toolBarFocusListener != null)
c.addFocusListener(toolBarFocusListener);
if (isRolloverBorders())
setBorderToRollover(c);
else
setBorderToNonRollover(c);
//## Bug FIXIssue 51(https://code.google.com/p/beautyeye/issues/detail?id=51)
//* 由Jack Jiang201210-12日注释掉它样做将导致各种放入的组
//* 如文本框等都将透明从而不绘制该 组件的背景那就错误了哦
//* 其实以下代码原本是为了解决放入到JToggleButton的白色背景问题现在它
//* 已经在BEToolgleButtonUI里解决了此处就不需要了也不应该要
// //* 只有它一行是由jb2011加的
// if(c instanceof JComponent)
// ((JComponent)c).setOpaque(false);
}
@Override
public void componentRemoved(ContainerEvent evt) {
Component c = evt.getChild();
if (toolBarFocusListener != null)
c.removeFocusListener(toolBarFocusListener);
// Revert the button border
setBorderToNormal(c);
}
}
//* 本类由Jack Jiang实现参考了com.sun.java.swing.plaf.windows.WindowsBorders.getToolBarBorder
/**
* 工具条边框左边或右或上方有拖动触点的绘制方便 告之用户它是可以拖动的 A border for the ToolBar. If the
* ToolBar is floatable then the handle grip is drawn
* <p>
* @since 1.4
*/
public static class ToolBarBorder extends AbstractBorder implements UIResource, SwingConstants {
/**
* The shadow.
*/
protected Color shadow;
/**
* The highlight.
*/
protected Color highlight;
protected Insets insets;
/**
* Instantiates a new tool bar border.
*
* @param shadow the shadow
* @param highlight the highlight
*/
public ToolBarBorder(Color shadow, Color highlight, Insets insets) {
this.highlight = highlight;
this.shadow = shadow;
this.insets = insets;
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y,
int width, int height) {
g.translate(x, y);
//需要绘制拖动触点
if (((JToolBar) c).isFloatable()) {
boolean vertical = ((JToolBar) c).getOrientation() == VERTICAL;
//虚线样式
Stroke oldStroke = ((Graphics2D) g).getStroke();
Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_BEVEL, 0, new float[] { 1, 1 }, 0);//实线空白
((Graphics2D) g).setStroke(sroke);
// int gap_top = 5,gap_bottom = 4; //10,-1
if (!vertical) {
int gap_top = 8, gap_bottom = 8;
if (c.getComponentOrientation().isLeftToRight()) {
int drawX = 3;
drawTouchH(g, drawX, gap_top - 1, drawX, height - gap_bottom - 1);
} else {
int drawX = 3 - 1;
drawTouchH(g, width - drawX, gap_top - 1, width - drawX, height - gap_bottom - 1);
}
} else // Vertical
{
int gap_left = 8, gap_right = 8;
int drawY = 3;
drawTouchV(g, gap_left - 1, drawY, width - gap_right - 1, drawY);
}
((Graphics2D) g).setStroke(oldStroke);
}
g.translate(-x, -y);
}
//水平工具条的触点绘制方法
private void drawTouchH(Graphics g, int x1, int y1, int x2, int y2) {
//第1条竖虚线深色
g.setColor(shadow);
g.drawLine(x1, y1, x1, y2 - 1);
//第2条竖虚线与第1条形成立体效果的浅色Y坐标相对第1条下偏一个像素
g.setColor(highlight);
g.drawLine(x1 + 1, y1 + 1, x1 + 1, y2);
//第3条竖虚线
g.setColor(shadow);
g.drawLine(x1 + 2, y1, x1 + 2, y2 - 1);
//第4条竖虚线与第3条形成立体效果的浅色Y坐标相对第3条下偏一个像素
g.setColor(highlight);
g.drawLine(x1 + 3, y1 + 1, x1 + 3, y2);
}
//垂直工具条的触点绘制方法
private void drawTouchV(Graphics g, int x1, int y1, int x2, int y2) {
//第1条横虚线深色
g.setColor(shadow);
g.drawLine(x1, y1, x2 - 1, y2);
//第2条横虚线与第1条形成立体效果的浅色X坐标相对第1条右偏一个像素
g.setColor(highlight);
g.drawLine(x1 + 1, y1 + 1, x2, y2 + 1);
//第3条横虚线
g.setColor(shadow);
g.drawLine(x1, y1 + 2, x2 - 1, y2 + 2);
//第4条横虚线与第3条形成立体效果的浅色X坐标相对第3条右偏一个像素
g.setColor(highlight);
g.drawLine(x1 + 1, y1 + 3, x2, y2 + 3);
}
@Override
public Insets getBorderInsets(Component c) {
//** 根据toolbar所放面板的方位不同而设置不一样的border参照的目标是水平toolbar时的insets
//tollbar上下设置的空白多一点看起来大气一些它也将决定toolbar的整体高度和宽度哦
final Insets DEFAILT_IS = insets;//8,0,9,0);//6, 0, 11, 0);
Insets is = DEFAILT_IS;
if (c instanceof JToolBar) {
Container parent = c.getParent();
if (parent != null) {
LayoutManager lm = parent.getLayout();
if (lm instanceof BorderLayout) {
Object cons = ((BorderLayout) lm).getConstraints((JToolBar) c);
if (cons != null)
if (cons.equals(BorderLayout.NORTH))
is = DEFAILT_IS;
else if (cons.equals(BorderLayout.SOUTH))
is = new Insets(DEFAILT_IS.bottom, 0, DEFAILT_IS.top, 0);
else if (cons.equals(BorderLayout.WEST))
is = new Insets(0, DEFAILT_IS.top, 0, DEFAILT_IS.bottom);
else if (cons.equals(BorderLayout.EAST))
is = new Insets(0, DEFAILT_IS.bottom, 0, DEFAILT_IS.top);
}
}
}
return getBorderInsets(c, is);//5, 0, 10, 0));//默认是 1,1,1,1
}
@Override
public Insets getBorderInsets(Component c, Insets insets) {
// insets.top = insets.left = insets.bottom = insets.right = 1;
if (((JToolBar) c).isFloatable()) {
// int gripInset = (XPStyle.getXP() != null) ? 12 : 9;//原windows外观中默认的
int gripInset = 9;
if (((JToolBar) c).getOrientation() == HORIZONTAL)
if (c.getComponentOrientation().isLeftToRight())
insets.left = gripInset;
else
insets.right = gripInset;
else
insets.top = gripInset;
}
return insets;
}
}
}

Some files were not shown because too many files have changed in this diff Show More