VS 2010: Change color of lines based on a pattern - visual-studio-2010

How can I change color of lines in Visual Studio 2010 based on some custom pattern? For example, I want to change color of all lines that start with logger. . Is it possible at all?
I have ReSharper 5 installed too.

I wrote up a quick little extension to do this; since you'll very likely want to modify it, you should grab the source. The important part is the code in LayoutChanged:
void ViewLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
{
IWpfTextView view = sender as IWpfTextView;
var adornmentLayer = view.GetAdornmentLayer("HighlightLines");
foreach (var line in e.NewOrReformattedLines)
{
if (line.Extent.GetText().StartsWith("logger.", StringComparison.OrdinalIgnoreCase))
{
Rectangle rect = new Rectangle()
{
Width = view.ViewportWidth + view.MaxTextRightCoordinate,
Height = line.Height,
Fill = Brushes.AliceBlue
};
Canvas.SetTop(rect, line.Top);
Canvas.SetLeft(rect, 0);
adornmentLayer.AddAdornment(line.Extent, null, rect);
}
}
}
To build/run this, you'll need to:
Download the VS2010 SDK.
Create a new project from the editor extension templates (I usually pick Visual C# -> Extensibility -> Editor Text Adornment).
Delete all the source files it creates.
Add HighlightMatchingLines.cs to the project.
F5 to run/test.
If you want to change the brush, change the Fill = Brushes.AliceBlue line.
If you want to change what text is matched, changed the condition in the if expression.
If you want to change what file type the extension is loaded for, change the [ContentType] attribute. The "Content Types" section of this msdn page lists out some of the common ones.

Related

Windows Forms c++ cannot set default values in datagrid cells

I've just started working with Windows Forms on Visual Studio 2019. I am most familiar with C++ and thus have been creating an application with C++/CLI. The basis of the project is that I have a schedule generating set of functions these are called in MyForm.h which is the main form originally launched. MyForm.h also opens MyForm2.h when a button is pressed. This MyForm2.h is where I have a problem. I want to allow the user to edit a series of specific settings for the schedule generator. The most user friendly way I've found to do this is with a datagrid using textboxes and checkmarks, but I need to have the original timeslots for the schedule in the datagrid for the user to edit when the open MyForm2.h.
I've looked all over to find how to set default values for a datagrid, but have only come up with two ok methods, both of which have some fatal flaws.
The first was from this microsoft guide.
The problem here is that the solution is written in c#, and I don't know how to implement it in a c++ program.
The second was from a few sites which generally displayed one of two formats which are displayed here in a way that is formatted to how I used them in my forms:
void InitializeComponent()
{
this->dgvStudents = (gcnew System::Windows::Forms::DataGridView());
this->dataGridViewTextBoxColumn1 = (gcnew System::Windows::Forms::DataGridViewTextBoxColumn());
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->dgvStudents))->BeginInit();
this->SuspendLayout();
this->dgvStudents->Columns->Add(this->dataGridViewTextBoxColumn1);
this->dgvStudents->Location = System::Drawing::Point(0, 0);
this->dgvStudents->Name = L"dgvStudents";
this->dgvStudents->Size = System::Drawing::Size(350, 100);
this->dgvStudents->TabIndex = 0;
//
// dataGridViewTextBoxColumn1
//
this->dataGridViewTextBoxColumn1->HeaderText = L"First Name";
this->dataGridViewTextBoxColumn1->Name = L"dataGridViewTextBoxColumn1";
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(638, 261);
this->Controls->Add(this->dgvStudents);
this->Name = L"MyForm3";
this->StartPosition = System::Windows::Forms::FormStartPosition::CenterScreen;
this->Text = L"Exercise";
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->dgvStudents))->EndInit();
this->ResumeLayout(false);
// Option 1
this->dgvStudents->Rows[0]->Cells[0]->Value = "MLP";
// Option 2
this->dgvStudents->Rows->Add("MLP");
}
I have tried putting both options in several various parts of the InitializeComponent() function and it makes no difference. The problem with Option 2 of this second solution is that it will be removed from the code if I change anything in the [Design] part of the MyForm2.h code editor in VS and save it. Weirdly, Option 1 will not be displayed in the [Design] part of the code and instead I will get the error Member Cells not found in class System.Windows.Forms.DataGridViewRowCollection, but if I launch the debugger for the program, both options will be displayed exactly how I want them to be in the GUIs that appear. As previously meantioned though, both options will most likely be removed if I change anything else in the form designer. Any help would be greatly appreciated:)

How can I change the Font of a TListBox's items?

I'm building an app with RAD Studio 11, but I can't find a way to change the item font of my TListBox.
I tried to change TListBox.Font in the Object Inspector, but when I select my TListBox called ingredientsDataBase in the Object Inspector, I can just change TListBox settings instead of TListBox.Items settings.
I add a TListBoxItem manually as follow:
Then, I can change ListBoxItem1.Font in the Object Inspector, after selecting my ListBoxItem1 (no problem).
The problem is that, when I run my program, the Font change only affects my ListBoxItem1, and I want the same Font for every item that I add to my TListBox.
UPDATE 1
After your help I tried to convert your Delphi code to C++.
__fastcall TIngredientCreator::addButtonClick(TObject *Sender){
//More code Here
//Then I ADD a new ListBoxItem to my ListBox "ingredientsDataBase"
ingredientsDataBase->Items->Add("newIngredient");
TListBoxItem *lbItem = new TListBoxItem(ingredientsDataBase);
lbItem->Parent = ingredientsDataBase;
// Remove Family and Size from the items TStyledSettings
lbItem->StyledSettings = lbItem->StyledSettings << TStyledSetting::Family << TStyledSetting::Size;
// You can now set these TextSettings as needed
lbItem->TextSettings->Font->Family = "Algerian";
lbItem->TextSettings->Font->Size = 18;
lbItem->Text = "algerian";
delete lbItem;
}
There is no syntax error, but I can't associate my new ListBoxItem, in this case the Text or Name of that new ListBoxItem called "newIngredient" (I don't know how to do it in this code), so when I run my program nothing happen to mi new Item at least.
UPDATE 2
I found a way to associate my newIngredient to TListBoxItem Object as follow:
int index = ingredientsDataBase->Items->IndexOf(newIngredient);
lbItem = ingredientsDataBase->ItemByIndex(index);
When I run the code and I add a new Ingredient, just the Text of the newIngredient is changed to "algerian", because in the first code I have this line lbItem->Text = "algerian" all good here. But Font and Size still without change.
Thanks for your answers
When you add items to the listbox, you need to clear some items from the default StyledSettings property of the new item, if you want to modify the corresponding TextSettings.
Here's an example in Delphi to do what you want:
procedure TForm5.Button2Click(Sender: TObject);
var
lbItem: TListBoxItem;
begin
lbItem := TListBoxItem.Create(ListBox1);
lbItem.Parent := ListBox1;
// Remove Family and Size from the items TStyledSettings
lbItem.StyledSettings := lbItem.StyledSettings - [TStyledSetting.Family,TStyledSetting.Size];
// You can now set these TextSettings as needed
lbItem.TextSettings.Font.Family := 'Algerian';
lbItem.TextSettings.Font.Size := 18;
lbItem.Text := 'algerian';
// In Embarcadero C++Builder you use the ">>" operator to remove members from a set, and "<<" to include them.
end;
After your help my code in a Multi-Device Application C++ Builder project result on the next code:
__fastcall TIngredientCreator::addButtonClick(TObject *Sender){
//More code Here
//Then I ADD a new ListBoxItem to my ListBox "ingredientsDataBase"
ingredientsDataBase->Items->Add("newIngredient");
int index = ingredientsDataBase->Items->IndexOf(newIngredient);
lbItem = ingredientsDataBase->ItemByIndex(index);
// Remove Family and Size from the items TStyledSettings
lbItem->StyledSettings = lbItem->StyledSettings >> TStyledSetting::Family >> TStyledSetting::Size;
// You can now set these TextSettings as needed
lbItem->TextSettings->Font->Family = "Consolas";
lbItem->TextSettings->Font->Size = 18;
delete lbItem;
}
If you are trying to do it in a Windows VCL Aplication C++ Builder Project is easier (You can change the font of the entire TListBox once):
ingredientsDataBase->Font->Size = 8.5;
ingredientsDataBase->Font->Name = "Consolas";

How to get the entire Visual Studio active document... with formatting

I know how to use VS Extensibility to get the entire active document's text. Unfortunately, that only gets me the text and doesn't give me the formatting, and I want that too.
I can, for example, get an IWpfTextView but once I get it, I'm not sure what to do with it. Are there examples of actually getting all the formatting from it? I'm only really interested in text foreground/background color, that's it.
Note: I need the formatted text on every edit, so unfortunately doing cut-and-paste using the clipboard is not an option.
Possibly the simplest method is to select all of the text and copy it to the clipboard. VS puts the rich text into the clipboard, so when you paste, elsewhere, you'll get the colors (assuming you handle rich text in your destination).
Here's my not-the-simplest solution. TL;DR: you can jump to the code at https://github.com/jimmylewis/GetVSTextViewFormattedTextSample.
The VS editor uses "classifications" to show segments of text which have special meaning. These classifications can then be formatted differently according to the language and user settings.
There's an API for getting the classifications in a document, but it didn't work for me. Or other people, apparently. But we can still get the classifications through an ITagAggregator<IClassificationTag>, as described in the preceding link, or right here:
[Import]
IViewTagAggregatorFactoryService tagAggregatorFactory = null;
// in some method...
var classificationAggregator = tagAggregatorFactory.CreateTagAggregator<IClassificationTag>(textView);
var wholeBufferSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, 0, textBuffer.CurrentSnapshot.Length);
var tags = classificationAggregator.GetTags(wholeBufferSpan);
Armed with these, we can rebuild the document. It's important to note that some text is not classified, so you have to piece everything together in chunks.
It's also notable that at this point, we have no idea how any of these tags are formatted - i.e. the colors used during rendering. If you want to, you can define your own mapping from IClassificationType to a color of your choice. Or, we can ask VS for what it would do using an IClassificationFormatMap. Again, remember, this is affected by user settings, Light vs. Dark theme, etc.
Either way, it could look something like this:
// Magic sauce pt1: See the example repo for an RTFStringBuilder I threw together.
RTFStringBuilder sb = new RTFStringBuilder();
var wholeBufferSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, 0, textBuffer.CurrentSnapshot.Length);
// Magic sauce pt2: see the example repo, but it's basically just
// mapping the spans from the snippet above with the formatting settings
// from the IClassificationFormatMap.
var textSpans = GetTextSpansWithFormatting(textBuffer);
int currentPos = 0;
var formattedSpanEnumerator = textSpans.GetEnumerator();
while (currentPos < wholeBufferSpan.Length && formattedSpanEnumerator.MoveNext())
{
var spanToFormat = formattedSpanEnumerator.Current;
if (currentPos < spanToFormat.Span.Start)
{
int unformattedLength = spanToFormat.Span.Start - currentPos;
SnapshotSpan unformattedSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, currentPos, unformattedLength);
sb.AppendText(unformattedSpan.GetText(), System.Drawing.Color.Black);
}
System.Drawing.Color textColor = GetTextColor(spanToFormat.Formatting.ForegroundBrush);
sb.AppendText(spanToFormat.Span.GetText(), textColor);
currentPos = spanToFormat.Span.End;
}
if (currentPos < wholeBufferSpan.Length)
{
// append any remaining unformatted text
SnapshotSpan unformattedSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, currentPos, wholeBufferSpan.Length - currentPos);
sb.AppendText(unformattedSpan.GetText(), System.Drawing.Color.Black);
}
return sb.ToString();
Hope this helps with whatever you're doing. The example repo will ask if you you want the formatted text in the clipboard after each edit, but that was just a dirty way that I could test and see that it worked. It's annoying, but it was just a PoC.

Is there a shortcut in VS to reformat a block of code to one line?

I'd like to be able to take this code block
var uVacationLandLubbers = new UserAttribute {
Name = "Land Lubbers",
Project = pVacation,
SystemUserAttribute = context.SystemUserAttributes.Single(x => x.Name == "Yes/No")
};
and reformat it to
var uVacationLandLubbers = new UserAttribute { Name = "Land Lubbers", Project = pVacation, SystemUserAttribute = context.SystemUserAttributes.Single(x => x.Name == "Yes/No") };
Is there a VS/Resharper/Other way of doing this?
This solution would not fully satisy your requirements, but help you considerably.
In Visual Studio, navigate to Tools -> Options.
In Options window, on the left select the language of your choice, say C#. Under C#, select Formatting -> New Lines. Once you select New Lines, a set of rules would be displayed on the right side, uncheck the following rules:
Place open brace on new line for types
Place open brace on new line for anonymous methods
Place open brace on new line for anonymous types
Place open brace on new line for object initializers
Place memebers in object initializers in new line
Place memebers in anonymous types in new line
Note: While unchecking a preview of the rule would be displayed which would help you to view the changes.
Once you do these settings, use this shortcut Ctrl + K + D to format the document.
Use shortcut Ctrl + K + D to format the document code

How to indent the first line of a paragraph in CKEditor

I'm using CKEditor and I want to indent just the first line of the paragraph. What I've done before is click "Source" and edit the <p> style to include text-indent:12.7mm;, but when I click "Source" again to go back to the normal editor, my changes are gone and I have no idea why.
My preference would be to create a custom toolbar button, but I'm not sure how to do so or where to edit so that clicking a custom button would edit the <p> with the style attribute I want it to have.
Depending on which version of CKE you use, your changes most likely disappear because ether the style attribute or the text-indent style is not allowed in the content. This is due to the Allowed Content Filter feature of CKEditor, read more here: http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter
Like Ervald said in the comments, you can also use CSS to do this without adding the code manually - however, your targeting options are limited. Either you have to target all paragraphs or add an id or class property to your paragraph(s) and target that. Or if you use a selector like :first-child you are restricted to always having the first element indented only (which might be what you want, I don't know :D).
To use CSS like that, you have to add the relevant code to contents.css, which is the CSS file used in the Editor contents and also you have to include it wherever you output the Editor contents.
In my opinion the best solution would indeed be making a plugin that places an icon on the toolbar and that button, when clicked, would add or remove a class like "indentMePlease" to the currently active paragraph. Developing said plugin is quite simple and well documented, see the excellent example at http://docs.ckeditor.com/#!/guide/plugin_sdk_sample_1 - if you need more info or have questions about that, ask in the comments :)
If you do do that, you again need to add the "indentMePlease" style implementation in contents.css and the output page.
I've got a way to indent the first line without using style, because I'm using iReport to generate automatic reports. Jasper does not understand styles. So I assign by jQuery an onkeydown method to the main iframe of CKEditor 4.6 and I check the TAB and Shift key to do and undo the first line indentation.
// TAB
$(document).ready(function(){
startTab();
});
function startTab() {
setTimeout(function(){
var $iframe_document;
var $iframe;
$iframe_document = $('.cke_wysiwyg_frame').contents();
$iframe = $iframe_document.find('body');
$iframe.keydown(function(e){
event_onkeydown(e);
});
},300);
}
function event_onkeydown(event){
if(event.keyCode===9) { // key tab
event.preventDefault();
setTimeout(function(){
var editor = CKEDITOR.instances['editor1'], //get your CKEDITOR instance here
range = editor.getSelection().getRanges()[0],
startNode = range.startContainer,
element = startNode.$,
parent;
if(element.parentNode.tagName != 'BODY') // If you take an inner element of the paragraph, get the parentNode (P)
parent = element.parentNode;
else // If it takes BODY as parentNode, it updates the inner element
parent = element;
if(event.shiftKey) { // reverse tab
var res = parent.innerHTML.toString().split(' ');
var aux = [];
var count_space = 0;
for(var i=0;i<res.length;i++) {
// console.log(res[i]);
if(res[i] == "")
count_space++;
if(count_space > 8 || res[i] != "") {
if(!count_space > 8)
count_space = 9;
aux.push(res[i]);
}
}
parent.innerHTML = aux.join(' ');
}
else { // tab
var spaces = " ";
parent.innerHTML = spaces + parent.innerHTML;
}
},200);
}
}

Resources