Added rotation of presentation view.

Change-Id: Iea68b7740c5e7cf9380c91b8b85ff02fd9c11b8e
This commit is contained in:
Andrzej J.R. Hunt
2012-08-14 12:59:22 +02:00
parent e1fb965edb
commit e02468f6e8
18 changed files with 339 additions and 190 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 B

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/handle_vertical_light" android:state_activated="true"/>
<item android:drawable="@drawable/handle_vertical_light" android:state_pressed="true"/>
<item android:drawable="@drawable/handle_vertical_light" android:state_focused="true"/>
<item android:drawable="@drawable/handle_vertical_default"/>
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/presentation_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical" >
<pl.polidea.coverflow.CoverFlow
xmlns:coverflow="http://schemas.android.com/apk/res/org.libreoffice.impressremote"
android:id="@+id/presentation_coverflow"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dip"
coverflow:imageHeight="150dip"
coverflow:imageWidth="180dip"
coverflow:withReflection="false" />
<TextView
android:id="@+id/presentation_slidenumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="" />
</LinearLayout>
<ImageView
android:id="@+id/presentation_handle"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:contentDescription="@string/presentation_ui_resizehandle"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:scaleType="fitXY"
android:src="@drawable/handle" />
<ScrollView
android:id="@+id/presentation_scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<WebView
android:id="@+id/presentation_notes"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout>

View File

@@ -5,24 +5,29 @@
android:orientation="vertical" > android:orientation="vertical" >
<TextView <TextView
android:id="@+id/textView1" android:id="@+id/pairing_instruction1"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_margin="10dip"
android:gravity="center"
android:text="@string/pairing_instructions_1" /> android:text="@string/pairing_instructions_1" />
<TextView <TextView
android:id="@+id/textView2" android:id="@+id/pairing_instruction2_deviceName"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:text="@string/pairing_instructions_2" /> android:layout_margin="10dip"
android:gravity="center"
android:text="@string/pairing_instructions_2_deviceName" />
<TextView <TextView
android:id="@+id/textView3" android:id="@+id/pairing_instruction3"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_margin="10dip"
android:text="@string/pairing_instructions_3" /> android:text="@string/pairing_instructions_3" />
<TextView <TextView
@@ -30,7 +35,9 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_margin="10dip"
android:text="" android:text=""
android:textAppearance="?android:attr/textAppearanceLarge" /> android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="75dip" />
</LinearLayout> </LinearLayout>

View File

@@ -24,7 +24,7 @@
<string name="wifi">WI-FI</string> <string name="wifi">WI-FI</string>
<string name="selector_noservers">Searching for computers…</string> <string name="selector_noservers">Searching for computers…</string>
<string name="pairing_instructions_1">In Impress, click on the "Slideshow" menu and select "Impress Remote".</string> <string name="pairing_instructions_1">In Impress, click on the "Slideshow" menu and select "Impress Remote".</string>
<string name="pairing_instructions_2">Choose "{1}" as your device.</string> <string name="pairing_instructions_2_deviceName">Choose "{1}" as your device.</string>
<string name="pairing_instructions_3">Then input this PIN:</string> <string name="pairing_instructions_3">Then input this PIN:</string>
</resources> </resources>

View File

@@ -8,26 +8,36 @@
*/ */
package org.libreoffice.impressremote; package org.libreoffice.impressremote;
import java.text.MessageFormat;
import org.libreoffice.impressremote.communication.CommunicationService; import org.libreoffice.impressremote.communication.CommunicationService;
import org.libreoffice.impressremote.communication.CommunicationService.State;
import android.app.Activity; import android.app.Activity;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.widget.TextView; import android.widget.TextView;
public class PairingActivity extends Activity { public class PairingActivity extends Activity {
private CommunicationService mCommunicationService;
private boolean mIsBound = false;
private TextView mPinText; private TextView mPinText;
/** Called when the activity is first created. */ /** Called when the activity is first created. */
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pairing);
bindService(new Intent(this, CommunicationService.class), mConnection,
Context.BIND_IMPORTANT);
mIsBound = true;
mPinText = (TextView) findViewById(R.id.pairing_pin); mPinText = (TextView) findViewById(R.id.pairing_pin);
@@ -46,6 +56,33 @@ public class PairingActivity extends Activity {
// refreshLists(); // refreshLists();
} }
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName aClassName,
IBinder aService) {
setContentView(R.layout.activity_pairing);
((TextView) findViewById(R.id.pairing_instruction2_deviceName))
.setText(MessageFormat
.format(getResources()
.getString(R.string.pairing_instructions_2_deviceName),
mCommunicationService
.getDeviceName()));
mCommunicationService = ((CommunicationService.CBinder) aService)
.getService();
if (mCommunicationService.getState() == State.CONNECTING) {
mPinText.setText(mCommunicationService.getPairingPin());
}
}
@Override
public void onServiceDisconnected(ComponentName aClassName) {
mCommunicationService = null;
}
};
private BroadcastReceiver mListener = new BroadcastReceiver() { private BroadcastReceiver mListener = new BroadcastReceiver() {
@Override @Override

View File

@@ -7,6 +7,7 @@ import pl.polidea.coverflow.AbstractCoverFlowImageAdapter;
import pl.polidea.coverflow.CoverFlow; import pl.polidea.coverflow.CoverFlow;
import android.app.Fragment; import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
@@ -57,9 +58,6 @@ public class PresentationFragment extends Fragment {
mNotes.loadData(summary, "text/html", null); mNotes.loadData(summary, "text/html", null);
mNotes.setBackgroundColor(Color.TRANSPARENT); mNotes.setBackgroundColor(Color.TRANSPARENT);
// TextView aText = new TextView();
// aText.setText
mTopView = (CoverFlow) v.findViewById(R.id.presentation_coverflow); mTopView = (CoverFlow) v.findViewById(R.id.presentation_coverflow);
mLayout = v.findViewById(R.id.presentation_layout); mLayout = v.findViewById(R.id.presentation_layout);
@@ -111,17 +109,20 @@ public class PresentationFragment extends Fragment {
break; break;
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
LayoutParams aParams = mTopView.getLayoutParams(); LayoutParams aParams = mTopView.getLayoutParams();
int aHeight = mTopView.getHeight();
int aViewSize = mLayout.getHeight();
final int DRAG_MARGIN = 120; final int DRAG_MARGIN = 120;
boolean aPortrait = (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
int aFlowSize = mTopView.getHeight();
int aViewSize = mLayout.getHeight();
// Calculate height change, taking limits into account // Calculate height change, taking limits into account
int aDiff = (int) (aEvent.getY()); int aDiff = (int) (aPortrait ? aEvent.getY() : aEvent.getX());
if (aDiff + aHeight < DRAG_MARGIN) { if (aDiff + aFlowSize < DRAG_MARGIN) {
aDiff = DRAG_MARGIN - aHeight; aDiff = DRAG_MARGIN - aFlowSize;
} else if ((aHeight + aDiff) > (aViewSize - DRAG_MARGIN)) { } else if ((aFlowSize + aDiff) > (aViewSize - DRAG_MARGIN)) {
aDiff = (aViewSize - DRAG_MARGIN) - aHeight; aDiff = (aViewSize - DRAG_MARGIN) - aFlowSize;
} }
// Now deal with the internal height // Now deal with the internal height
@@ -130,15 +131,27 @@ public class PresentationFragment extends Fragment {
double aRatio = mOriginalCoverflowWidth double aRatio = mOriginalCoverflowWidth
/ mOriginalCoverflowHeight; / mOriginalCoverflowHeight;
float aHeightNew = mTopView.getImageHeight() + aDiff; float aHeightNew;
float aWidthNew = (float) (aRatio * aHeightNew); float aWidthNew;
if (aPortrait) {
aHeightNew = mTopView.getImageHeight() + aDiff;
aWidthNew = (float) (aRatio * aHeightNew);
// Too wide -- so scale down // Too wide -- so scale down
if (aWidthNew > mLayout.getWidth() - 50) { if (aWidthNew > mLayout.getWidth() - 50) {
aWidthNew = mLayout.getWidth() - 50; aWidthNew = mLayout.getWidth() - 50;
aHeightNew = (float) (aWidthNew / aRatio); aHeightNew = (float) (aWidthNew / aRatio);
aDiff = (int) (aHeightNew - mTopView.getImageHeight()); aDiff = (int) (aHeightNew - mTopView.getImageHeight());
} }
} else {
aWidthNew = mTopView.getImageWidth();
aHeightNew = (float) (aWidthNew / aRatio);
// Too High -- so scale down
if (aHeightNew > mLayout.getHeight() - 50) {
aHeightNew = mLayout.getHeight() - 50;
aWidthNew = (float) (aHeightNew / aRatio);
aDiff = (int) (aWidthNew - mTopView.getImageWidth());
}
}
mNewCoverflowHeight = aHeightNew; mNewCoverflowHeight = aHeightNew;
mNewCoverflowWidth = aWidthNew; mNewCoverflowWidth = aWidthNew;

View File

@@ -158,9 +158,9 @@ public class SelectorActivity extends Activity {
aLayout); aLayout);
TextView aText = (TextView) aView TextView aText = (TextView) aView
.findViewById(R.id.selector_sub_label); .findViewById(R.id.selector_sub_label);
aView.setOnClickListener(mClickListener); aText.setOnClickListener(mClickListener);
aText.setText(aServer.getName()); aText.setText(aServer.getName());
aMap.put(aServer, aView); aMap.put(aServer, aText);
} }
} }
@@ -182,7 +182,6 @@ public class SelectorActivity extends Activity {
@Override @Override
public void onClick(View aView) { public void onClick(View aView) {
// TODO Auto-generated method stub
mCommunicationService.stopFindingServers(); mCommunicationService.stopFindingServers();
Server aDesiredServer = null; Server aDesiredServer = null;

View File

@@ -32,6 +32,7 @@ public abstract class Client {
protected InputStream mInputStream; protected InputStream mInputStream;
protected BufferedReader mReader; protected BufferedReader mReader;
protected OutputStream mOutputStream; protected OutputStream mOutputStream;
protected String mPin = "";
public abstract void closeConnection(); public abstract void closeConnection();
@@ -79,6 +80,10 @@ public abstract class Client {
} }
public String getPin() {
return mPin;
}
/** /**
* Send a valid JSON string to the server. * Send a valid JSON string to the server.
* *

View File

@@ -27,6 +27,22 @@ public class CommunicationService extends Service implements Runnable {
private State mState = State.DISCONNECTED; private State mState = State.DISCONNECTED;
public State getState() {
return mState;
}
public String getPairingPin() {
if (mClient != null)
return mClient.getPin();
else
return "";
}
public String getDeviceName() {
return "Bob";
// FIXME: get the device name somehow.
}
private State mStateDesired = State.DISCONNECTED; private State mStateDesired = State.DISCONNECTED;
private Server mServerDesired = null; private Server mServerDesired = null;

View File

@@ -17,7 +17,6 @@ import java.util.Random;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.StrictMode;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
/** /**
@@ -33,10 +32,6 @@ public class NetworkClient extends Client {
public NetworkClient(String ipAddress, Context aContext) { public NetworkClient(String ipAddress, Context aContext) {
super(aContext); super(aContext);
// FIXME: eventually networking will be fully threaded.
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
try { try {
mSocket = new Socket(ipAddress, PORT); mSocket = new Socket(ipAddress, PORT);
mInputStream = mSocket.getInputStream(); mInputStream = mSocket.getInputStream();
@@ -45,10 +40,14 @@ public class NetworkClient extends Client {
mOutputStream = mSocket.getOutputStream(); mOutputStream = mSocket.getOutputStream();
// Pairing. // Pairing.
Random aRandom = new Random(); Random aRandom = new Random();
String aPin = "" + aRandom.nextInt(10000); String aPin = "" + (aRandom.nextInt(9000) + 1000);
while (aPin.length() < 4) {
aPin = "0" + aPin; // Add leading zeros if necessary
}
Intent aIntent = new Intent( Intent aIntent = new Intent(
CommunicationService.MSG_PAIRING_STARTED); CommunicationService.MSG_PAIRING_STARTED);
aIntent.putExtra("PIN", aPin); aIntent.putExtra("PIN", aPin);
mPin = aPin;
LocalBroadcastManager.getInstance(mContext).sendBroadcast(aIntent); LocalBroadcastManager.getInstance(mContext).sendBroadcast(aIntent);
// Send out // Send out
String aName = "Bob"; // TODO: get the proper name String aName = "Bob"; // TODO: get the proper name

View File

@@ -8,6 +8,8 @@ import java.net.InetAddress;
import java.net.SocketException; import java.net.SocketException;
import java.util.HashMap; import java.util.HashMap;
import org.libreoffice.impressremote.communication.Server.Protocol;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
@@ -93,6 +95,14 @@ public class ServerFinder {
mFinishRequested = false; mFinishRequested = false;
// TODO: Remove for production
mServerList.put("10.0.2.2",
new Server(Protocol.NETWORK, "10.0.2.2",
"Android Emulator Localhost", System
.currentTimeMillis()));
Intent aIntent = new Intent(CommunicationService.MSG_SERVERLIST_CHANGED);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(aIntent);
if (mListenerThread == null) { if (mListenerThread == null) {
mListenerThread = new Thread() { mListenerThread = new Thread() {
@Override @Override