Thursday, May 3, 2012

GIT snippet #2

Aliases Very handfull way to make your console interaction easier. Here we go. Basic:
git config --global alias.go checkout
git config --global alias.st status
git config --global alias.gc commit
git config --global alias.br branch
git config --global alias.gr rebase
git config --global alias.gs stash
git config --global alias.l pull
git config --global alias.p push
Hardcore:
git config --global alias.grm rebase master
git config --global alias.god checkout dev
git config --global alias.gom checkout master
git config --global alias.gmd merge dev
So usual commit-push cycle would be:
git gc -a -m "master"
git gom // checkout master
git l   // pull
git god // checkout dev
git grm // rebase master
git gom // checkout master
git gmd // merge dev
git p   // push
git god // git checkout dev
Want more hardcore? We can write this to bash aliases, just add this lines to ~/.bashrc:
alias gl='git pull'
alias gp='git push'
alias gs='git status'
alias gc='git commit'
alias gcm='git commit -a -m'
alias go='git checkout'
alias gb='git branch'
alias gs='git status'
alias god='git checkout dev'
alias gom='git checkout master'
alias gmd='git merge dev'
alias grm='git rebase master'
alias grc='git rebase --continue'
alias gra='git rebase --abort'
So now our commit-push cycle would be:
gc -a -m "master"
gom // checkout master
gl   // pull
god // checkout dev
grm // rebase master
gom // checkout master
gmd // merge dev
gp   // push
god // git checkout dev
And if you want to automate rebase this action, you can write a bash script:
#!/bin/bash

branch=$1

cd ~/projects/$branch
git checkout dev
git stash
git checkout master
git pull
git checkout dev
git rebase master
if grep -q $commitString <<< $output; then
 git reset HEAD^
fi 
git stash apply
cd "`pwd`"
You can call this script by ./script.sh project_name This script will also rollback if you have rebase conflicts. Then better actually do such an action manually.

Wednesday, May 2, 2012

GIT Snippet

Just a tiny git snippet for those, who are not familiar with git. So here we go: Create repo
mkdir new_project
cd new_project
git init
touch README.MD
git add .
git commit -a -m "initial commit"
or clone existing repo for example - existing github repo
git clone git@github.com:username/some_existing_project.git
cd some_existing_project
if you want to keep track repo:
git remote add upstream git://github.com/username/some_existing_project.git
git fetch upstream
Create branch
git checkout -b dev
Now we have a special branch dev for development. After some changes are made, and some task is complete, we may want to merge them with original branch. Actually better use not usual merge command, but more powerfull rebase So: Commit and rebase
git add .
git commit -a -m "Commit message. Write some small one row title about the problem solved."
git checkout master
git pull
git checkout dev
git rebase master
Solve rebase conflicts If there are some conflicts, you should solve them by any merge-helper tool (IDE's usually have them), or manually. Then
git add .
git rebase --continue
or if you want to abort rebase
git rebase --abort
after succesfull rebase you may want to push changes to the origin gitrepo Push to origin
git checkout master
git merge dev
git push
git checkout dev
That's all. This is all basis that you need to work with git. More complex actions may appear, but they are not so often. Here are some links:

Mixing a trait dynamically. Copy a trait

Fantastically! I was dreaming about this for a long time. Imagine you have a trait, like
trait Dated {
 def createDate: Date
 def createAuthor: Author
}
Just some trait form db orm entity. What if you want just set nececery fields to this Dated instance, without any knowledge what case class is it, like:
def setEntityDate(entity: Dated) = entity.copy(createDate = /*now*/, createAuthor = /*currentUser*/)
This task can be accomplished by scala macroses, read about it here http://stackoverflow.com/questions/10373318/mixing-in-a-trait-dynamically and here https://gist.github.com/2559714

Friday, April 27, 2012

Bye bye Dear Flash. Adobe HTML

Hello fellas. As you know, Adobe Flash is loosing its positions as a web engine for last years. Mobile platforms created a new vector of development, which has a different direction with Flash's one. Mobile platforms, pads, Apple empire, nyan html5 and css3 had left for Flash only web games and enterprise areas. The few adventages, which still flash has, are 3d engines and rich enterprise apps legacy. I am sure Adobe doesn't want to lose it's positions, so I guess they are going to target html-like enterprise area. A couple of days ago they presented HTML and CSS themed website -
As we can see, the whole website is totally size flexible. Adobe definetly wants to cover all types of devices. I think they really disliked Google and Apple rejection of Flash technology, so this really is going to be a war within html area technologies. I guess Adobe is going to present a new large-scale ultimate framework, which will cover large area of web development, like:
  • Mobile development - although a lot of attemts from flash, that is still a huge Adobe's gap
  • Cross-browser/cross-device oriented engine - they will definetely leave cross browser orientation feature. What is absent now - they will push tecnology to Apple and Android by using html5+js+css3
  • Enterprise sector - or yeah, of course we will have it
  • Common web engine - Flash definetely lacks it now. I really can not use Adobe Flash right now for a usual website. They should really make a new engine common-friendly
That's it. Adobe would do this in nearest year or two, or would finally leave web framework arena. This isn't actually clear right now, but what we do know, is... Flash is leaving us. Bye bye old friend.

Sunday, March 18, 2012

Adobe Flex Flow Tabs Layout

Today we are going to create flow layout for spark tabs. When we have large amount of tabs, there appears a problem to layout them into small horizontal width. Default spark TabBar layout just resizes them to smaller width and trims buttons labels. It looks like this:


To solve this problem we can implement html-like custom spark flow layout. Create LayoutBase class and override two methods:
  • measure() - this method measures layout component size, based on its elements size. In our case this is height, which depends on component width.
  • updateDisplayList(width:Number, height:Number) - method to position elements. Elements position depends on the component width
 Lets see updateDisplayList. Method comes through all elements. Measures its width and height. If element size overcomes container width, we go to the next row. Then we position element by estimated horizontal and vertical coordinates.


override public function updateDisplayList(width:Number, height:Number):void {
 super.updateDisplayList(width,height);
 var currentElement:ILayoutElement;
 var elementHeight:Number;
 var elementWidth:Number;
 var rowHeight:Number = 0;
 var verticalPosition:Number = 0;
 var horizontalPosition:Number = 0;
 if (!target) return;
 var childrenCount:int = target.numElements;
 for (var i:int = 0; i< childrenCount; i++) {
  currentElement = target.getElementAt(i);
  //Reset element size to retrieve its original one
  currentElement.setLayoutBoundsSize(NaN,NaN);
  elementHeight = currentElement.getPreferredBoundsHeight();
  elementWidth = currentElement.getPreferredBoundsWidth();
  //Last element in a row
  if(horizontalPosition + elementWidth >
  width ) {
   horizontalPosition = 0;
   verticalPosition += rowHeight;
   rowHeight = 0;
  }
  rowHeight = Math.max(elementHeight, rowHeight);
  //Set element position
  currentElement.setLayoutBoundsPosition(horizontalPosition, verticalPosition);
  horizontalPosition += elementWidth;
 }
 //Invalidate targetr measuredHeight, if it is incorrect
 if(target.measuredHeight != verticalPosition + rowHeight) {
  target.invalidateSize();
 }
}
In the end we check, if target measuredHeight is not the same with estimated elements height, and if so we cal invalidateSize() method on target. This method call measure() to update measured size - measuredHeight in our case.


override public function measure():void
  {
   super.measure();
   if (!target) return;
   
   var childrenCount:int = target.numElements;
   
   var currentElement:ILayoutElement;
   var maxWidth:Number = 0;
   var maxHeight:Number = 0;
   var elementMaxX:Number;
   var elementMaxY:Number;
   
   for(var i:int = 0; i< childrenCount; i++)
   {    
    currentElement = target.getElementAt(i);
    elementMaxX = currentElement.getLayoutBoundsX() + currentElement.getPreferredBoundsWidth();
    elementMaxY = currentElement.getLayoutBoundsY() + currentElement.getPreferredBoundsHeight();
    if(maxWidth < elementMaxX) maxWidth = elementMaxX;
    if(maxHeight < elementMaxY) maxHeight = elementMaxY;
   }
   target.measuredWidth = maxWidth;
   target.measuredHeight = maxHeight;
  }
As we see  - this is very easy. Measure method goes through all elements and just retrievs maximum size, which is necessary to allocate this elements.

So here is a final demo: