public int RECENT_FILES_LIMIT = 50;
public int CONSOLE_COMMAND_HISTORY_LIMIT = 300;
public int EDITOR_TAB_LIMIT = 10;
+ public int EDITOR_TAB_TITLE_LIMIT = 30;
public boolean ANIMATE_WINDOWS = true;
public int ANIMATION_SPEED = 2000; // Pixels per second
public boolean SHOW_TOOL_WINDOW_NUMBERS = true;
<grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <xy x="20" y="20" width="500" height="527"/>
+ <xy x="20" y="20" width="500" height="585"/>
</constraints>
<properties/>
<border type="none"/>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
- <grid id="eb8d0" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="10">
+ <grid id="eb8d0" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="10">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</clientProperties>
<border type="none" title-resource-bundle="messages/ApplicationBundle" title-key="group.tab.closing.policy"/>
<children>
- <grid id="5a5a7" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="5a5a7" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<children>
<component id="527a6" class="javax.swing.JLabel">
<constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="60" height="27"/>
+ </grid>
</constraints>
<properties>
<text resource-bundle="messages/ApplicationBundle" key="editbox.tab.limit"/>
<component id="16477" class="javax.swing.JTextField" binding="myEditorTabLimitField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false">
- <preferred-size width="30" height="-1"/>
+ <preferred-size width="30" height="27"/>
</grid>
</constraints>
<properties>
<text value="15"/>
</properties>
</component>
+ <component id="2479d" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="messages/ApplicationBundle" key="editbox.tab.title.limit"/>
+ </properties>
+ </component>
+ <component id="3499c" class="javax.swing.JTextField" binding="myTabTitleLimitField">
+ <constraints>
+ <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="30" height="27"/>
+ </grid>
+ </constraints>
+ <properties>
+ <columns value="2"/>
+ <text value="30"/>
+ </properties>
+ </component>
</children>
</grid>
<grid id="9b723" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="2">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<grid id="611cc" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="2">
<margin top="10" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
private JCheckBox myShowCloseButtonOnCheckBox;
private JCheckBox myShowDirectoryInTabCheckBox;
private JRadioButton myActivateRightNeighbouringTabRadioButton;
+ private JTextField myTabTitleLimitField;
public EditorTabsConfigurable() {
myEditorTabPlacement.setModel(new DefaultComboBoxModel(new Object[]{
myHideKnownExtensions.setSelected(uiSettings.HIDE_KNOWN_EXTENSION_IN_TABS);
myShowDirectoryInTabCheckBox.setSelected(uiSettings.SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES);
myEditorTabLimitField.setText(Integer.toString(uiSettings.EDITOR_TAB_LIMIT));
+ myTabTitleLimitField.setText(Integer.toString(uiSettings.EDITOR_TAB_TITLE_LIMIT));
myShowCloseButtonOnCheckBox.setSelected(uiSettings.SHOW_CLOSE_BUTTON);
if (uiSettings.CLOSE_NON_MODIFIED_FILES_FIRST) {
uiSettings.ACTIVATE_RIGHT_EDITOR_ON_CLOSE = myActivateRightNeighbouringTabRadioButton.isSelected();
String temp = myEditorTabLimitField.getText();
- if(temp.trim().length() > 0){
+ if (temp.trim().length() > 0) {
try {
int newEditorTabLimit = Integer.parseInt(temp);
- if(newEditorTabLimit>0&&newEditorTabLimit!=uiSettings.EDITOR_TAB_LIMIT){
- uiSettings.EDITOR_TAB_LIMIT=newEditorTabLimit;
+ if (newEditorTabLimit > 0 && newEditorTabLimit != uiSettings.EDITOR_TAB_LIMIT) {
+ uiSettings.EDITOR_TAB_LIMIT = newEditorTabLimit;
uiSettingsChanged = true;
}
- }catch (NumberFormatException ignored){}
+ }
+ catch (NumberFormatException ignored) {
+ }
+ }
+ temp = myTabTitleLimitField.getText();
+ if (temp.trim().length() > 0) {
+ try {
+ int newTabTitleLimit = Integer.parseInt(temp);
+ newTabTitleLimit = Math.max(10, Math.min(100, newTabTitleLimit));
+ if (newTabTitleLimit != uiSettings.EDITOR_TAB_TITLE_LIMIT){
+ uiSettings.EDITOR_TAB_TITLE_LIMIT = newTabTitleLimit;
+ uiSettingsChanged = true;
+ }
+ }
+ catch (NumberFormatException ignored) {
+ }
}
if(uiSettingsChanged){
uiSettings.fireUISettingsChanged();
boolean isModified = isModified(myCbModifiedTabsMarkedWithAsterisk, uiSettings.MARK_MODIFIED_TABS_WITH_ASTERISK);
isModified |= isModified(myShowTabsTooltipsCheckBox, uiSettings.SHOW_TABS_TOOLTIPS);
isModified |= isModified(myEditorTabLimitField, uiSettings.EDITOR_TAB_LIMIT);
+ isModified |= isModified(myTabTitleLimitField, uiSettings.EDITOR_TAB_TITLE_LIMIT);
int tabPlacement = ((Integer)myEditorTabPlacement.getSelectedItem()).intValue();
isModified |= tabPlacement != uiSettings.EDITOR_TAB_PLACEMENT;
isModified |= myHideKnownExtensions.isSelected() != uiSettings.HIDE_KNOWN_EXTENSION_IN_TABS;
* out of its container. (IDEA-61536)
*/
private WeakReference<TabInfo> myPreviousSelection = new WeakReference<TabInfo>(null);
+ private boolean myTitleShortened;
public TabInfo(final JComponent component) {
myComponent = component;
return myPreviousSelection.get();
}
+ public boolean isTitleShortened() {
+ return myTitleShortened;
+ }
+
+ public void setTitleIsShortened(boolean titleIsShortened) {
+ myTitleShortened = titleIsShortened;
+ }
+
public interface DragOutDelegate {
void dragOutStarted(MouseEvent mouseEvent, TabInfo info);
*/
public class JBEditorTabs extends JBTabsImpl {
public static final String TABS_ALPHABETICAL_KEY = "tabs.alphabetical";
+ static final String TABS_CHORTEN_TITLE_IF_NEED = "tabs.shorten.title.if.need";
private JBEditorTabsPainter myDarkPainter = new DarculaEditorTabsPainter();
private JBEditorTabsPainter myDefaultPainter = new DefaultEditorTabsPainter();
return super.createSingleRowLayout();
}
+ @Override
+ protected TabLabel createTabLabel(TabInfo info) {
+ TabLabel label = super.createTabLabel(info);
+ label.putClientProperty(TABS_CHORTEN_TITLE_IF_NEED, Boolean.TRUE);
+ return label;
+ }
+
@Override
public boolean isEditorTabs() {
return true;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.util.Pass;
import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.*;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.ui.tabs.JBTabsPosition;
public void setText(final SimpleColoredText text) {
+ myInfo.setTitleIsShortened(false);
+ if (text != null && text.getTexts().size() == 1 && Boolean.TRUE == getClientProperty(JBEditorTabs.TABS_CHORTEN_TITLE_IF_NEED)) {
+ String title = text.getTexts().get(0);
+ if (title.length() > UISettings.getInstance().EDITOR_TAB_TITLE_LIMIT) {
+ SimpleTextAttributes attributes = text.getAttributes().get(0);
+ text.clear();
+ text.append(StringUtil.getShortened(title, UISettings.getInstance().EDITOR_TAB_TITLE_LIMIT), attributes);
+ myInfo.setTitleIsShortened(true);
+ }
+ }
myLabel.change(new Runnable() {
public void run() {
myLabel.clear();
myTabs.getTabAt(index).setTooltipText(text);
}
+ public boolean isTitleShortened(int index) { return myTabs.getTabAt(index).isTitleShortened(); }
+
public void setBackgroundColorAt(final int index, final Color color) {
myTabs.getTabAt(index).setTabColor(color);
}
}
}
+ private boolean isTitleShortenedAt(int index) {
+ return myTabbedPane != null && myTabbedPane.isTitleShortened(index);
+ }
+
private void setBackgroundColorAt(final int index, final Color color) {
if (myTabbedPane != null) {
myTabbedPane.setBackgroundColorAt(index, color);
final int index = findEditorIndex(findFileComposite(file));
if (index != -1) {
setTitleAt(index, EditorTabbedContainer.calcTabTitle(getManager().getProject(), file));
- setToolTipTextAt(index, UISettings.getInstance().SHOW_TABS_TOOLTIPS ? getManager().getFileTooltipText(file) : null);
+ setToolTipTextAt(index, UISettings.getInstance().SHOW_TABS_TOOLTIPS || isTitleShortenedAt(index)
+ ? getManager().getFileTooltipText(file)
+ : null);
}
}
checkbox.show.code.folding.outline=Show code folding outline
group.tab.appearance=Tab Appearance
editbox.tab.limit=Tab limit:
+editbox.tab.title.limit=Tab title limit:
combobox.editor.tab.placement=Placement:
checkbox.editor.tabs.in.single.row=Show tabs in single row
checkbox.editor.tabs.show.close.button=Show "close" button on editor tabs
return s.startsWith(smallPart.toLowerCase()) && bigPart.toLowerCase().startsWith(s);
}
+ public static String getShortened(String s, int maxWidth) {
+ int length = s.length();
+ if (isEmpty(s) || length <= maxWidth) return s;
+ ArrayList<String> words = new ArrayList<String>();
+
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < length; i++) {
+ char ch = s.charAt(i);
+
+ if (i == length - 1) {
+ builder.append(ch);
+ words.add(builder.toString());
+ builder.delete(0, builder.length());
+ continue;
+ }
+
+ if (i > 0 && (ch == '/' || ch == '.' || Character.isUpperCase(ch))) {
+ words.add(builder.toString());
+ builder.delete(0, builder.length());
+ }
+ builder.append(ch);
+ }
+
+ int removedLength = 0;
+
+ String toPaste = "...";
+ int index;
+ while (true) {
+ index = Math.max(0, words.size() / 2 - 1);
+ String aWord = words.get(index);
+ words.remove(index);
+ if (words.size() < 2) {
+ int toCut = length - removedLength - maxWidth + 3;
+ int pos = (aWord.length() - toCut) / 2;
+ toPaste = aWord.substring(0, pos) + "..." + aWord.substring(pos+toCut);
+ break;
+ }
+ removedLength += aWord.length();
+ if (length - removedLength <= maxWidth - 3) {
+ break;
+ }
+ }
+ for (int i = 0; i < words.size(); i++) {
+ String word = words.get(i);
+ if (i == index || words.size() == 1) builder.append(toPaste);
+ builder.append(word);
+ }
+ return builder.toString().replaceAll("\\.{4,}", "...");
+ }
+
/**
* Expirable CharSequence. Very useful to control external library execution time,
* i.e. when java.util.regex.Pattern match goes out of control.
assertEquals(Arrays.asList("\n", "\r\n", "\n", "\r\n", "\r", "\r", "aa\r", "bb\r\n", "cc\n", "\r", "dd\n", "\n", "\r\n", "\r"),
Arrays.asList(StringUtil.splitByLinesKeepSeparators("\n\r\n\n\r\n\r\raa\rbb\r\ncc\n\rdd\n\n\r\n\r")));
}
+
+ public void testShortened() {
+ String[] names = {"AVeryVeeryLongClassName.java", "com.test.SomeJAVAClassName.java", "strangelowercaseclassname.java"};
+ for (String name : names) {
+ for (int i = name.length() + 1; i > 15; i--) {
+ String shortened = StringUtil.getShortened(name, i);
+ assertTrue(shortened.length() <= i);
+ assertTrue(!shortened.contains("...."));
+ }
+ }
+ }
}