Tabs Studio Blog (organizing Visual Studio document tabs)

September 22, 2010

Visual Studio 2008 style explained

Filed under: Uncategorized — Tags: — Sergey Vlasov @ 8:16 am

Please, read the Overlapping sloped tabs post first for the general approach to tab shape customization. Let’s have a closer look at default tabs in Visual Studio 2008:

Tabs in Visual Studio 2008 (2x zoom)

Tabs in Visual Studio 2008 (2x zoom)


Below the tabs you can see the frame border that is overlapped by the selected tab. Tabs Studio window with tabs overlaps default tabs and two pixels of this border. In the Visual Studio 2008 style for Tabs Studio we are going to recreate overlapped top of the border:

<Border Height="2" BorderBrush="#69A1BF" BorderThickness="1,1,1,0" Background="White"/>

Selected tab needs to overlap the border. For that we increase z-index for tabs panel with background from 0 to 1 and later specify bottom margin for the selected tab as -2:

          <Grid Panel.ZIndex="1">
          ...
          <Trigger Property="IsTabSelected" Value="True">                           <!--Selected tab-->
            <Setter Property="Margin" Value="0,2,-9,-2"/>

Right margin for tabs is set to -9: it is amount of horizontal overlap between the adjacent tabs. With negative right margin the right border of tabs also overlaps the last tab in a row. To prevent overlap of the last tab in a row, we set buffering right margin of tabs to 10:

<Style TargetType="TabsStudio:Tabs" BasedOn="{StaticResource DefaultTabsStyle}">
  <Setter Property="Margin" Value="0,0,10,0"/>
</Style>

The selected tab has different shape, background and border comparing to default tabs. We create separate descriptions for these properties depending on the value of the IsTabSelected property. For the selected tab, the left side geometry is the following figure:

                <PathGeometry>
                  <PathFigure StartPoint="4 21">
                    <LineSegment Point="-16 21" IsStroked="false"/>
                    <LineSegment Point="-16 18.5" IsStroked="false"/>
                    <BezierSegment Point1="-1 1" Point2="-1 1" Point3="4 0" IsStroked="true" IsSmoothJoin="true"/>
                  </PathFigure>
                </PathGeometry>

The top bound of this figure is 0 – this is the rule for sides in Shaper. The right bound of this figure is 4 – making the slope overlap the tab contents by 4 pixels. An additional segment is automatically added by WPF from the end point to the start point to close the figure. For choosing Bezier control point values (Point1 and Point2) you can try the BezierExperimenter sample code from the “Applications = Code + Markup” book, chapter 28 (C# download, VB download).

The left bound of the right side figure is -3 – making the right side figure overlap the tab contents by 3 pixels (it doesn’t actually overlap the tab name because tab content has right margin 4):

                <PathGeometry>
                  <PathFigure StartPoint="-3 21">
                    <LineSegment Point="-1 21" IsStroked="false"/>
                    <LineSegment Point="-1 18.5" IsStroked="false"/>
                    <LineSegment Point="-1 2" IsStroked="true"/>
                    <LineSegment Point="-3 0" IsStroked="true"/>
                  </PathFigure>
                </PathGeometry>

The selected tab is 2 pixels higher than normal tabs – it has top margin 2 while normal tabs have top margin 4. Finally, selected tab font is bold and there is no close tab button:

<Style TargetType="TabsStudio:TabName" BasedOn="{StaticResource DefaultTabNameStyle}">
  <Style.Triggers>
    <Trigger Property="IsTabSelected" Value="True">
      <Setter Property="Control.FontWeight" Value="Bold"/>
    </Trigger>
  </Style.Triggers>
</Style>

<Style TargetType="TabsStudio:CloseTabButton" BasedOn="{StaticResource DefaultCloseTabButtonStyle}">
  <Setter Property="Visibility" Value="Collapsed"/>
</Style>

Here is the final Visual Studio 2008 style:

Visual Studio 2008 style in Tabs Studio (2x zoom)

Visual Studio 2008 style in Tabs Studio (2x zoom)

September 21, 2010

Overlapping sloped tabs

Filed under: Uncategorized — Tags: , — Sergey Vlasov @ 7:39 pm

I’ve extended Tabs Studio and created the Shaper add-in to make it possible to create customizable sloped tabs in Tabs Studio. To test the new capabilities, I tried to emulate default tabs of Visual Studio 2008 and Google Chrome. The results look almost exactly the same:

Tabs in Visual Studio 2008

Tabs in Visual Studio 2008


Visual Studio 2008 style in Tabs Studio

Visual Studio 2008 style in Tabs Studio


Tabs in Google Chrome

Tabs in Google Chrome


Chrome style in Tabs Studio

Chrome style in Tabs Studio

I’ll describe the new Visual Studio 2008 style in the next post. For now, let’s see what was added to Tabs Studio and how Shaper works.

TabsHost in Tabs Studio

Control tree now has a new root element TabsHost. The new root of the style specification is now:

TabsHost : ContentControl
|
 - Tabs : Panel (IsGroupSelected, IsGroupFocused for VS 2010, IsGroupWithLastActiveDocument for VS 2010)
   |
   ...

Introduction of TabsHost allows a tabs panel to be shifted and makes possible addition of other visual elements and controls at the tabs panel level. The DefaultTabsHostStyle is already a template using a rectangle behind the tabs to draw a background:

<Style x:Key="DefaultTabsHostStyle" TargetType="TabsStudio:TabsHost">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type TabsStudio:TabsHost}">
        <Grid>
          <Rectangle Width="{TemplateBinding Width}"
                     Height="{TemplateBinding Height}"
                     Fill="{TemplateBinding Background}"/>
          <ContentPresenter/>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Shaper

The first function of the Shaper add-in is to manage z-order of tabs so that tab #1 overlaps tab #2, tab #2 overlaps tab #3 and so on (default z-order is inverse). Shaper also sets z-index for the selected tab to overlap all others.

The second function of Shaper is the TabShape control. It is similar to the Border control, but specialized for trapezoid tabs. TabShape has LeftSide and RightSide properties of type Geometry plus Background Brush and Border Pen properties.

TabShape draws the central rectangular part of the trapezoid scaled to the tab content, draws the top border, draws sides and places tab content in the “middle”. Specifying negative and positive coordinates for left and right sides you control how sides overlap the content. All TabShape properties can be dynamically customized in style depending for example on whether tab is selected or not. Here is an example of the LeftSide geometry for the selected tab from the Visual Studio 2008 style (IsStroked property for each segment controls whether it drawn or not):

<Setter TargetName="TabShape" Property="LeftSide">
  <Setter.Value>
    <PathGeometry>
      <PathFigure StartPoint="4 21">
        <LineSegment Point="-16 21" IsStroked="false"/>
        <LineSegment Point="-16 18.5" IsStroked="false"/>
        <BezierSegment Point1="-1 1" Point2="-1 1" Point3="4 0" IsStroked="true" IsSmoothJoin="true"/>
      </PathFigure>
    </PathGeometry>
  </Setter.Value>
</Setter>

Download links

August 26, 2010

ASP.NET MVC tabs grouping and coloring

Filed under: Uncategorized — Tags: , — Sergey Vlasov @ 1:29 pm

I’ve created the MvcGroup add-in that groups ASP.NET MVC controller and view tabs near each other (a controller is placed before views). This add-in also adds IsController, IsView and GroupName properties that can be used to color MVC tabs by type and/or by group name. See the following two examples:

<Style TargetType="TabsStudio:Tab" BasedOn="{StaticResource DefaultTabStyle}">
  <Style.Triggers>
    <MultiTrigger>
      <MultiTrigger.Conditions>
        <Condition Property="TabsStudioMvcGroup:Properties.IsController" Value="True"/>
        <Condition Property="IsTabSelected" Value="False"/>
      </MultiTrigger.Conditions>
      <Setter Property="Background">
        <Setter.Value>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <GradientStop Color="#F5F5F5" Offset="0"/>
            <GradientStop Color="#B0D0B0" Offset="1"/>
          </LinearGradientBrush>
        </Setter.Value>
      </Setter>
    </MultiTrigger>
    <MultiTrigger>
      <MultiTrigger.Conditions>
        <Condition Property="TabsStudioMvcGroup:Properties.IsView" Value="True"/>
        <Condition Property="IsTabSelected" Value="False"/>
      </MultiTrigger.Conditions>
      <Setter Property="Background">
        <Setter.Value>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <GradientStop Color="#F5F5F5" Offset="0"/>
            <GradientStop Color="#B0B0D0" Offset="1"/>
          </LinearGradientBrush>
        </Setter.Value>
      </Setter>
    </MultiTrigger>
  </Style.Triggers>
</Style>
ASP.NET MVC tabs grouping and coloring by type

ASP.NET MVC tabs grouping and coloring by type

<Style TargetType="TabsStudio:Tab" BasedOn="{StaticResource DefaultTabStyle}">
  <Style.Triggers>
    <MultiTrigger>
      <MultiTrigger.Conditions>
        <Condition Property="TabsStudioMvcGroup:Properties.GroupName" Value="Account"/>
        <Condition Property="IsTabSelected" Value="False"/>
      </MultiTrigger.Conditions>
      <Setter Property="Background">
        <Setter.Value>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <GradientStop Color="#F5F5F5" Offset="0"/>
            <GradientStop Color="#B0D0B0" Offset="1"/>
          </LinearGradientBrush>
        </Setter.Value>
      </Setter>
    </MultiTrigger>
    <MultiTrigger>
      <MultiTrigger.Conditions>
        <Condition Property="TabsStudioMvcGroup:Properties.GroupName" Value="Home"/>
        <Condition Property="IsTabSelected" Value="False"/>
      </MultiTrigger.Conditions>
      <Setter Property="Background">
        <Setter.Value>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <GradientStop Color="#F5F5F5" Offset="0"/>
            <GradientStop Color="#B0B0D0" Offset="1"/>
          </LinearGradientBrush>
        </Setter.Value>
      </Setter>
    </MultiTrigger>
  </Style.Triggers>
</Style>
ASP.NET MVC tabs grouping and coloring by group name

ASP.NET MVC tabs grouping and coloring by group name

Download link: MvcGroup v1.0.0.

August 20, 2010

Per project tab coloring

Filed under: Uncategorized — Tags: , — Sergey Vlasov @ 8:52 am

As the Decorator add-in demonstrated, it is easy to add project properties to tabs and use it for coloring. I decided to write the separate Projector add-in that explicitly adds the project name property to tabs.

With the Projector installed, to color tabs for the ClassLibrary2 project with purple you can use the following style:

<Style TargetType="TabsStudio:Tab" BasedOn="{StaticResource DefaultTabStyle}">
    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="TabsStudioProjector:Properties.ProjectName" Value="ClassLibrary2"/>
                <Condition Property="IsTabSelected" Value="False"/>
            </MultiTrigger.Conditions>
            <Setter Property="Background">
                <Setter.Value>
                     <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                         <GradientStop Color="#F5F5F5" Offset="0"/>
                         <GradientStop Color="#B0B0F0" Offset="1"/>
                     </LinearGradientBrush>
                </Setter.Value>
            </Setter>
        </MultiTrigger>
    </Style.Triggers>
</Style>
Purple tab from the ClassLibrary2 project

Purple tab from the ClassLibrary2 project

Finding and assigning a distinct color for each project in a solution could be hard. Assigning a single color to a group of projects is more practical, except WPF doesn’t have direct capability to trigger match between a project name and a list of names. Projector adds custom IsAnyOfConverter inherited from System.Windows.Data.IValueConverter to support this scenario. The custom Convert function of the converter receives tab’s project name as the value parameter, comma separated list of project names for a color as the parameter parameter and returns true if tab’s project name is in the list:

public object Convert(object value, System.Type targetType,
    object parameter, System.Globalization.CultureInfo culture)
{
    string[] allowedValues = ((string)parameter).Split(new System.Char[] { ',' });
    return ((System.Collections.Generic.IList)allowedValues).Contains((string)value);
}

To use this converter in XAML we define it as a static resource and invoke in a data trigger:

<TabsStudioProjector:IsAnyOfConverter x:Key="IsAnyOf" />

<Style TargetType="TabsStudio:Tab" BasedOn="{StaticResource DefaultTabStyle}">
    <Style.Triggers>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition Binding="{Binding Path=(TabsStudioProjector:Properties.ProjectName), 
                        RelativeSource={RelativeSource Self}, 
                        Converter={StaticResource IsAnyOf},
                        ConverterParameter='ClassLibrary3,ClassLibrary4'}" 
                        Value="True"/>
                <Condition Binding="{Binding Path=IsTabSelected, RelativeSource={RelativeSource Self}}" Value="False"/>
            </MultiDataTrigger.Conditions>
            <Setter Property="Background">
                <Setter.Value>
                     <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                         <GradientStop Color="#F5F5F5" Offset="0"/>
                         <GradientStop Color="#A0C0A0" Offset="1"/>
                     </LinearGradientBrush>
                </Setter.Value>
            </Setter>
        </MultiDataTrigger>
    </Style.Triggers>
</Style>
Green tabs from the ClassLibrary3 and ClassLibrary4 projects

Green tabs from the ClassLibrary3 and ClassLibrary4 projects

Using the same technique it is possible, for example, to create a regex converter matching tab’s project name with a regular expression specified as the parameter.

Download link: Projector v1.0.

May 8, 2010

Styling tabs in a separate window

Filed under: Uncategorized — Tags: , — Sergey Vlasov @ 7:43 pm

In Visual Studio 2010 default style for tabs uses left and right margins of 1 pixel:

<Style x:Key="DefaultTabsStyle" TargetType="TabsStudio:Tabs">
  <Setter Property="Margin" Value="1,0,1,0"/>
</Style>

It makes transition between Tabs Studio tabs and Visual Studio border under the tabs in the left and right corners smooth:

Left tab margin

Left tab margin


When tabs are in a separate window, default margins create white lines to the left and to the right of the tabs:
White lines to the left and to the right of the tabs

White lines to the left and to the right of the tabs


Setting margins to 0 removes these lines:

<Style TargetType="TabsStudio:Tabs" BasedOn="{StaticResource DefaultTabsStyle}">
  <Setter Property="Margin" Value="0,0,0,0"/>
</Style>

Excessive tabs margins removed

Excessive tabs margins removed

Another useful customization for tabs in a separate window is tabs background. The default background in VS 2010 style is transparent, it results in dark blue for normal tabs placement and white for tabs in a separate window. As an example, the following style sets tabs background to dark blue:

<Style TargetType="TabsStudio:Tabs" BasedOn="{StaticResource DefaultTabsStyle}">
  <Setter Property="Background" Value="#293955"/>
</Style>

Dark blue tabs background

Dark blue tabs background


A similar style can be used to customize tabs background in VS 2008, which is by default grey control brush.

April 13, 2010

Updated Visual Studio 2010 tab style

Filed under: Uncategorized — Tags: , — Sergey Vlasov @ 11:38 am

I’ve changed selected tab colors to match the default VS 2010 theme – yellow for active, dark blue for inactive and grey for unfocused:

Active and inactive tabs

Active and inactive tabs


Unfocused tabs

Unfocused tabs

April 12, 2010

Close file buttons

Filed under: Uncategorized — Tags: — Sergey Vlasov @ 10:41 pm

I’ve added the close file button to each extension. It should be particularly useful in SSMS where you more often need to close a file rather than a whole tab:

Close file buttons in SSMS

Close file buttons in SSMS


In the default style these buttons are collapsed, but you can use all usual properties in a custom style to make them visible. For example, the following style makes close file buttons visible on the selected tab and hides the close tab button in a tab when it contains more than a one extension:

<Style TargetType="TabsStudio:TabExtensionCloseButton" BasedOn="{StaticResource DefaultTabExtensionCloseButton}">
  <Style.Triggers>
    <Trigger Property="IsTabSelected" Value="True">
      <Setter Property="Visibility" Value="Visible"/>
    </Trigger>
  </Style.Triggers>
</Style>

<Style TargetType="TabsStudio:CloseTabButton" BasedOn="{StaticResource DefaultCloseTabButtonStyle}">
  <Style.Triggers>
    <Trigger Property="IsMultiExtensions" Value="True">
      <Setter Property="Visibility" Value="Collapsed"/>
    </Trigger>
  </Style.Triggers>
</Style>

January 23, 2010

Visual Studio 2010 Silver theme

Filed under: Uncategorized — Tags: , — Sergey Vlasov @ 3:24 pm

This month Matthew Johnson released the Visual Studio Color Theme Editor extension for Visual Studio 2010. This extension allows users to customize colors used by Visual Studio 2010 and contains three example themes (Autumn, Emerald and Silver):

Default Visual Studio 2010 theme

Default Visual Studio 2010 theme


Visual Studio 2010 Silver theme

Visual Studio 2010 Silver theme


Jameel Al-Aziz, in addition to his Tabs Studio 2010 style, has created Tabs Studio 2010 Silver theme style:
Tabs Studio 2010 Silver theme style

Tabs Studio 2010 Silver theme style


Get Tabs Studio 2010 Silver theme style by Jameel Al-Aziz (Visual Studio 2010 Beta 2 and Tabs Studio v1.7.6 or greater required).

November 24, 2009

Tabs Studio 2010 style by Jameel Al-Aziz

Filed under: Uncategorized — Tags: , — Sergey Vlasov @ 5:45 pm

Jameel did a great work designing Tabs Studio style perfectly matching Visual Studio 2010 theme:

Visual Studio 2010 style by Jameel Al-Aziz

Visual Studio 2010 style by Jameel Al-Aziz


His style requires Visual Studio 2010 Beta 2 and Tabs Studio v1.7.6. You can get this style here.

November 10, 2009

Animation effects

Filed under: Uncategorized — Tags: — Sergey Vlasov @ 9:05 pm

You can use WPF animation effects to customize Tabs Studio presentation. Tabs Studio v1.7.3 demonstrates fade effect for the yellow extension background when mouse is over it and transition effect between states for the close tab button. You can turn on these two effects in the Quick Style window:

Quick Style animate option

Quick Style animate option


For example, fade-in effect for an extension starts on mouse enter event, during 0.2 seconds it changes border color from transparent to gray and it changes yellow background from transparent to opaque:

  
<EventTrigger RoutedEvent="Control.MouseEnter">
  <EventTrigger.Actions>
    <BeginStoryboard>
      <Storyboard>
        <ColorAnimation  Duration="0:0:0.2" Storyboard.TargetName="Border"    Storyboard.TargetProperty="BorderBrush.Color"  To="Gray"/>
        <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetName="LabelText" Storyboard.TargetProperty="Background.Opacity" To="1"/>
      </Storyboard>
    </BeginStoryboard>
  </EventTrigger.Actions>
</EventTrigger>

Full sample effects definitions are available when you turn on animation and generate style in the Quick Style window. I think the most common customization for the sample effects provided will be adjustment of animation duration.

« Newer PostsOlder Posts »

Blog at WordPress.com.